Skip to content

Commit c8d0983

Browse files
committed
don't panic on extern with just multiple quotes in the name
1 parent 8111a2d commit c8d0983

File tree

4 files changed

+59
-26
lines changed

4 files changed

+59
-26
lines changed

compiler/rustc_span/src/symbol.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,12 +2510,24 @@ impl Ident {
25102510
Ident::new(self.name, span.with_ctxt(self.span.ctxt()))
25112511
}
25122512

2513-
/// Creates a new ident with the same span and name with leading quote removed, if any.
2514-
/// If called on an empty ident, or with name just a single quote, returns an empty ident which is invalid.
2513+
/// Creates a new ident with the same span and name with leading quotes removed, if any.
2514+
/// If called on an empty ident, or with name just single quotes, returns an empty ident which is invalid.
2515+
/// Creating empty ident will trigger debug assertions.
2516+
/// Use `without_first_quote_checked` instead if not certain this will return valid ident.
25152517
pub fn without_first_quote(self) -> Ident {
25162518
Ident::new(Symbol::intern(self.as_str().trim_start_matches('\'')), self.span)
25172519
}
25182520

2521+
/// Creates a new ident with the same span and name with leading quotes removed, if any.
2522+
/// If called on an empty ident, or with name just single quotes, returns `None`.
2523+
/// If you are certain this will return valid ident, use `without_first_quote` instead.
2524+
pub fn without_first_quote_checked(self) -> Option<Ident> {
2525+
match Symbol::intern(self.as_str().trim_start_matches('\'')) {
2526+
sym::empty => None,
2527+
name => Some(Ident::new(name, self.span)),
2528+
}
2529+
}
2530+
25192531
/// "Normalize" ident for use in comparisons using "item hygiene".
25202532
/// Identifiers with same string value become same if they came from the same macro 2.0 macro
25212533
/// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from
@@ -3099,15 +3111,16 @@ impl Ident {
30993111
}
31003112

31013113
pub fn is_raw_lifetime_guess(self) -> bool {
3102-
// Check that the name isn't just a single quote.
3114+
// Ident name might be an empty string or just single quotes, so call checked function.
31033115
// `self.without_first_quote()` would return empty ident, which triggers debug assert.
3104-
if self.name.as_str() == "'" {
3105-
return false;
3116+
match self.without_first_quote_checked() {
3117+
None => false,
3118+
Some(ident_without_apostrophe) => {
3119+
ident_without_apostrophe.name != self.name
3120+
&& ident_without_apostrophe.name.can_be_raw()
3121+
&& ident_without_apostrophe.is_reserved_lifetime()
3122+
}
31063123
}
3107-
let ident_without_apostrophe = self.without_first_quote();
3108-
ident_without_apostrophe.name != self.name
3109-
&& ident_without_apostrophe.name.can_be_raw()
3110-
&& ident_without_apostrophe.is_reserved_lifetime()
31113124
}
31123125

31133126
pub fn guess_print_mode(self) -> IdentPrintMode {

tests/ui/extern/extern-single-quote-issue-147365.rs renamed to tests/ui/extern/extern-only-quotes-issue-147365.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
// https://github.com/rust-lang/rust/issues/147365
44
// Ensures we don't trigger debug assert by creating an empty Ident when determining whether
5-
// the single quote is a raw lifetime.
5+
// the quotes are a raw lifetime.
66

77
extern "'" {} //~ ERROR invalid ABI: found `'`
88

9+
extern "''" {} //~ ERROR invalid ABI: found `''`
10+
11+
extern "'''" {} //~ ERROR invalid ABI: found `'''`
12+
913
fn main() {}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error[E0703]: invalid ABI: found `'`
2+
--> $DIR/extern-only-quotes-issue-147365.rs:7:8
3+
|
4+
LL | extern "'" {}
5+
| ^^^ invalid ABI
6+
|
7+
= note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
8+
help: there's a similarly named valid ABI `C`
9+
|
10+
LL - extern "'" {}
11+
LL + extern "C" {}
12+
|
13+
14+
error[E0703]: invalid ABI: found `''`
15+
--> $DIR/extern-only-quotes-issue-147365.rs:9:8
16+
|
17+
LL | extern "''" {}
18+
| ^^^^ invalid ABI
19+
|
20+
= note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
21+
22+
error[E0703]: invalid ABI: found `'''`
23+
--> $DIR/extern-only-quotes-issue-147365.rs:11:8
24+
|
25+
LL | extern "'''" {}
26+
| ^^^^^ invalid ABI
27+
|
28+
= note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
29+
30+
error: aborting due to 3 previous errors
31+
32+
For more information about this error, try `rustc --explain E0703`.

tests/ui/extern/extern-single-quote-issue-147365.stderr

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)