Why rust ignore lifetime checks on &str?

That's because all string literals have 'static lifetime. From the rust book:

One special lifetime we need to discuss is 'static, which means that this reference can live for the entire duration of the program. All string literals have the 'static lifetime, which we can annotate as follows:

let s: &'static str = "I have a static lifetime.";

The text of this string is stored directly in the program’s binary, which is always available. Therefore, the lifetime of all string literals is 'static


Fixed example:

fn main() {
    let strA = "a".to_string();
    let result;

    {
        let strB = "abc".to_string();
        result = longest(&strA, &strB); // Will return strB
    }

    println!("The longest string is {}", result); // compile error
}

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

Now produces a compiler error as expected:

error[E0597]: `strB` does not live long enough
  --> src/main.rs:7:33
   |
7  |         result = longest(&strA, &strB); // Will return strB
   |                                 ^^^^^ borrowed value does not live long enough
8  |     }
   |     - `strB` dropped here while still borrowed
9  | 
10 |     println!("The longest string is {}", result); // result now point to strB!!
   |                                          ------ borrow later used here

playground

Rust was not "ignoring" the lifetimes of the string variables in your initial example. When you set a variable to a string literal that literal gets hardcoded into the executable binary and gets a 'static lifetime which means it's valid for the entire duration of the program. If we add explicit type annotations to your initial example it should become clear why it compiles and works:

fn main() {
    let strA: &'static str = "a";
    let result;

    {
        let strB: &'static str = "abc";
        result = longest(&strA, &strB); // returns 'static str
    }

    println!("The longest string is {}", result); // prints result
}

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

However when we call to_string() on a string literal we create an owned and heap allocated String which lifetime's is non-static and is scoped to whatever block its in, hence making the change makes the program no longer compile as expected.