diff --git a/Cargo.lock b/Cargo.lock index 6a1525f7530d8..d02cab38ae8f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -782,7 +782,7 @@ dependencies = [ "declare_clippy_lint", "if_chain", "itertools", - "pulldown-cmark 0.9.2", + "pulldown-cmark", "quine-mc_cluskey", "regex-syntax", "rustc-semver", @@ -2555,7 +2555,7 @@ dependencies = [ "memchr", "once_cell", "opener", - "pulldown-cmark 0.9.2", + "pulldown-cmark", "regex", "serde", "serde_json", @@ -2572,7 +2572,7 @@ dependencies = [ "anyhow", "handlebars 3.5.5", "pretty_assertions", - "pulldown-cmark 0.7.2", + "pulldown-cmark", "same-file", "serde_json", "url", @@ -3269,17 +3269,6 @@ dependencies = [ "cc", ] -[[package]] -name = "pulldown-cmark" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca36dea94d187597e104a5c8e4b07576a8a45aa5db48a65e12940d3eb7461f55" -dependencies = [ - "bitflags", - "memchr", - "unicase", -] - [[package]] name = "pulldown-cmark" version = "0.9.2" @@ -4583,7 +4572,7 @@ name = "rustc_resolve" version = "0.0.0" dependencies = [ "bitflags", - "pulldown-cmark 0.9.2", + "pulldown-cmark", "rustc_arena", "rustc_ast", "rustc_ast_pretty", diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 8848ea3bb9aee..37ee0e14020c3 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -145,8 +145,13 @@ pub unsafe fn create_module<'ll>( let llvm_version = llvm_util::get_version(); if llvm_version < (16, 0, 0) { if sess.target.arch == "s390x" { + // LLVM 16 data layout changed to always set 64-bit vector alignment, + // which is conditional in earlier LLVM versions. + // https://reviews.llvm.org/D131158 for the discussion. target_data_layout = target_data_layout.replace("-v128:64", ""); } else if sess.target.arch == "riscv64" { + // LLVM 16 introduced this change so as to produce more efficient code. + // See https://reviews.llvm.org/D116735 for the discussion. target_data_layout = target_data_layout.replace("-n32:64-", "-n64-"); } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 4b3c0c055adfd..8c39feca88a0e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -471,6 +471,8 @@ pub enum StashKey { /// When an invalid lifetime e.g. `'2` should be reinterpreted /// as a char literal in the parser LifetimeIsChar, + /// When an invalid lifetime e.g. `'🐱` contains emoji. + LifetimeContainsEmoji, /// Maybe there was a typo where a comma was forgotten before /// FRU syntax MaybeFruTypo, diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 7122ccdcd2e9f..6d8f7e4a0f681 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -474,7 +474,7 @@ declare_features! ( /// Allows using the `non_exhaustive_omitted_patterns` lint. (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None), /// Allows `for` binders in where-clauses - (incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(1), None), + (incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(108185), None), /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2c99ab8071117..2ff47237b1bf4 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -252,6 +252,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // (*) -- not late-bound, won't change } + Some(rbv::ResolvedArg::Error(_)) => { + bug!("only ty/ct should resolve as ResolvedArg::Error") + } + None => { self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| { debug!(?lifetime, "unelided lifetime in signature"); @@ -2689,6 +2693,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let index = generics.param_def_id_to_index[&def_id.to_def_id()]; tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)) } + Some(rbv::ResolvedArg::Error(guar)) => tcx.ty_error_with_guaranteed(guar), arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"), } } @@ -2893,22 +2898,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::BareFn(bf) => { require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); - let fn_ptr_ty = tcx.mk_fn_ptr(self.ty_of_fn( + tcx.mk_fn_ptr(self.ty_of_fn( ast_ty.hir_id, bf.unsafety, bf.abi, bf.decl, None, Some(ast_ty), - )); - - if let Some(guar) = - deny_non_region_late_bound(tcx, bf.generic_params, "function pointer") - { - tcx.ty_error_with_guaranteed(guar) - } else { - fn_ptr_ty - } + )) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { self.maybe_lint_bare_trait(ast_ty, in_path); @@ -2917,21 +2914,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { TraitObjectSyntax::DynStar => ty::DynStar, }; - let object_ty = self.conv_object_ty_poly_trait_ref( - ast_ty.span, - bounds, - lifetime, - borrowed, - repr, - ); - - if let Some(guar) = bounds.iter().find_map(|trait_ref| { - deny_non_region_late_bound(tcx, trait_ref.bound_generic_params, "trait object") - }) { - tcx.ty_error_with_guaranteed(guar) - } else { - object_ty - } + self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr) } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); @@ -3392,24 +3375,3 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } - -fn deny_non_region_late_bound( - tcx: TyCtxt<'_>, - params: &[hir::GenericParam<'_>], - where_: &str, -) -> Option { - params.iter().find_map(|bad_param| { - let what = match bad_param.kind { - hir::GenericParamKind::Type { .. } => "type", - hir::GenericParamKind::Const { .. } => "const", - hir::GenericParamKind::Lifetime { .. } => return None, - }; - - let mut diag = tcx.sess.struct_span_err( - bad_param.span, - format!("late-bound {what} parameter not allowed on {where_} types"), - ); - - Some(if tcx.features().non_lifetime_binders { diag.emit() } else { diag.delay_as_bug() }) - }) -} diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 7bcaeadbcf67b..127d4fa908bb9 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -398,7 +398,12 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option {} Some(rbv::ResolvedArg::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {} - Some(rbv::ResolvedArg::LateBound(..) | rbv::ResolvedArg::Free(..)) | None => { + Some( + rbv::ResolvedArg::LateBound(..) + | rbv::ResolvedArg::Free(..) + | rbv::ResolvedArg::Error(_), + ) + | None => { self.has_late_bound_regions = Some(lt.ident.span); } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 8a110bfc2f7f5..c0c90e47a7539 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -50,7 +50,7 @@ impl RegionExt for ResolvedArg { fn id(&self) -> Option { match *self { - ResolvedArg::StaticLifetime => None, + ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None, ResolvedArg::EarlyBound(id) | ResolvedArg::LateBound(_, _, id) @@ -336,7 +336,57 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } } + + fn visit_poly_trait_ref_inner( + &mut self, + trait_ref: &'tcx hir::PolyTraitRef<'tcx>, + non_lifetime_binder_allowed: NonLifetimeBinderAllowed, + ) { + debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref); + + let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); + + let initial_bound_vars = binders.len() as u32; + let mut bound_vars: FxIndexMap = FxIndexMap::default(); + let binders_iter = + trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| { + let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param); + let r = late_arg_as_bound_arg(self.tcx, &pair.1, param); + bound_vars.insert(pair.0, pair.1); + r + }); + binders.extend(binders_iter); + + if let NonLifetimeBinderAllowed::Deny(where_) = non_lifetime_binder_allowed { + deny_non_region_late_bound(self.tcx, &mut bound_vars, where_); + } + + debug!(?binders); + self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders); + + // Always introduce a scope here, even if this is in a where clause and + // we introduced the binders around the bounded Ty. In that case, we + // just reuse the concatenation functionality also present in nested trait + // refs. + let scope = Scope::Binder { + hir_id: trait_ref.trait_ref.hir_ref_id, + bound_vars, + s: self.scope, + scope_type, + where_bound_origin: None, + }; + self.with(scope, |this| { + walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); + this.visit_trait_ref(&trait_ref.trait_ref); + }); + } +} + +enum NonLifetimeBinderAllowed { + Deny(&'static str), + Allow, } + impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; @@ -400,7 +450,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } } - let (bound_vars, binders): (FxIndexMap, Vec<_>) = + let (mut bound_vars, binders): (FxIndexMap, Vec<_>) = bound_generic_params .iter() .enumerate() @@ -411,6 +461,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }) .unzip(); + deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures"); + self.record_late_bound_vars(e.hir_id, binders); let scope = Scope::Binder { hir_id: e.hir_id, @@ -567,7 +619,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { match ty.kind { hir::TyKind::BareFn(c) => { - let (bound_vars, binders): (FxIndexMap, Vec<_>) = c + let (mut bound_vars, binders): (FxIndexMap, Vec<_>) = c .generic_params .iter() .enumerate() @@ -577,6 +629,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { (pair, r) }) .unzip(); + + deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types"); + self.record_late_bound_vars(ty.hir_id, binders); let scope = Scope::Binder { hir_id: ty.hir_id, @@ -596,7 +651,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |this| { for bound in bounds { - this.visit_poly_trait_ref(bound); + this.visit_poly_trait_ref_inner( + bound, + NonLifetimeBinderAllowed::Deny("trait object types"), + ); } }); match lifetime.res { @@ -967,39 +1025,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) { - debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref); - - let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); - - let initial_bound_vars = binders.len() as u32; - let mut bound_vars: FxIndexMap = FxIndexMap::default(); - let binders_iter = - trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| { - let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param); - let r = late_arg_as_bound_arg(self.tcx, &pair.1, param); - bound_vars.insert(pair.0, pair.1); - r - }); - binders.extend(binders_iter); - - debug!(?binders); - self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders); - - // Always introduce a scope here, even if this is in a where clause and - // we introduced the binders around the bounded Ty. In that case, we - // just reuse the concatenation functionality also present in nested trait - // refs. - let scope = Scope::Binder { - hir_id: trait_ref.trait_ref.hir_ref_id, - bound_vars, - s: self.scope, - scope_type, - where_bound_origin: None, - }; - self.with(scope, |this| { - walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); - this.visit_trait_ref(&trait_ref.trait_ref); - }); + self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow); } } @@ -1364,7 +1390,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { return; } - span_bug!(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}",); + self.tcx + .sess + .delay_span_bug(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}"); } #[instrument(level = "debug", skip(self))] @@ -1915,3 +1943,37 @@ fn is_late_bound_map( } } } + +pub fn deny_non_region_late_bound( + tcx: TyCtxt<'_>, + bound_vars: &mut FxIndexMap, + where_: &str, +) { + let mut first = true; + + for (var, arg) in bound_vars { + let Node::GenericParam(param) = tcx.hir().get_by_def_id(*var) else { + bug!(); + }; + + let what = match param.kind { + hir::GenericParamKind::Type { .. } => "type", + hir::GenericParamKind::Const { .. } => "const", + hir::GenericParamKind::Lifetime { .. } => continue, + }; + + let mut diag = tcx.sess.struct_span_err( + param.span, + format!("late-bound {what} parameter not allowed on {where_}"), + ); + + let guar = if tcx.features().non_lifetime_binders && first { + diag.emit() + } else { + diag.delay_as_bug() + }; + + first = false; + *arg = ResolvedArg::Error(guar); + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 4fe6c6618f698..fec04af231393 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -134,7 +134,8 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::Free(_, _) | rbv::ResolvedArg::EarlyBound(_) - | rbv::ResolvedArg::LateBound(_, _, _), + | rbv::ResolvedArg::LateBound(_, _, _) + | rbv::ResolvedArg::Error(_), ) | None, _, @@ -211,7 +212,8 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(_) | rbv::ResolvedArg::LateBound(_, _, _) - | rbv::ResolvedArg::Free(_, _), + | rbv::ResolvedArg::Free(_, _) + | rbv::ResolvedArg::Error(_), ) | None, _, diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 6e815863d06ff..e6f04fe0aaa63 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -95,7 +95,7 @@ pub enum TokenKind { Literal { kind: LiteralKind, suffix_start: u32 }, /// "'a" - Lifetime { starts_with_number: bool }, + Lifetime { starts_with_number: bool, contains_emoji: bool }, // One-char tokens: /// ";" @@ -630,7 +630,13 @@ impl Cursor<'_> { // If the first symbol is valid for identifier, it can be a lifetime. // Also check if it's a number for a better error reporting (so '0 will // be reported as invalid lifetime and not as unterminated char literal). - is_id_start(self.first()) || self.first().is_digit(10) + // We also have to account for potential `'🐱` emojis to avoid reporting + // it as an unterminated char literal. + is_id_start(self.first()) + || self.first().is_digit(10) + // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode + // 5.0, but Unicode is already newer than this. + || unic_emoji_char::is_emoji(self.first()) }; if !can_be_a_lifetime { @@ -643,16 +649,33 @@ impl Cursor<'_> { return Literal { kind, suffix_start }; } - // Either a lifetime or a character literal with - // length greater than 1. + // Either a lifetime or a character literal. let starts_with_number = self.first().is_digit(10); + let mut contains_emoji = false; - // Skip the literal contents. - // First symbol can be a number (which isn't a valid identifier start), - // so skip it without any checks. - self.bump(); - self.eat_while(is_id_continue); + // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode + // 5.0, but Unicode is already newer than this. + if unic_emoji_char::is_emoji(self.first()) { + contains_emoji = true; + } else { + // Skip the literal contents. + // First symbol can be a number (which isn't a valid identifier start), + // so skip it without any checks. + self.bump(); + } + self.eat_while(|c| { + if is_id_continue(c) { + true + // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode + // 5.0, but Unicode is already newer than this. + } else if unic_emoji_char::is_emoji(c) { + contains_emoji = true; + true + } else { + false + } + }); // Check if after skipping literal contents we've met a closing // single quote (which means that user attempted to create a @@ -662,7 +685,7 @@ impl Cursor<'_> { let kind = Char { terminated: true }; Literal { kind, suffix_start: self.pos_within_token() } } else { - Lifetime { starts_with_number } + Lifetime { starts_with_number, contains_emoji } } } diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs index e4c1787f2ccef..670d64fb983f5 100644 --- a/compiler/rustc_lexer/src/tests.rs +++ b/compiler/rustc_lexer/src/tests.rs @@ -235,7 +235,7 @@ fn lifetime() { check_lexing( "'abc", expect![[r#" - Token { kind: Lifetime { starts_with_number: false }, len: 4 } + Token { kind: Lifetime { starts_with_number: false, contains_emoji: false }, len: 4 } "#]], ); } diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 65a686857e5f3..ccf95992a6e6e 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { }); cx.emit_spanned_lint(DEREF_INTO_DYN_SUPERTRAIT, cx.tcx.def_span(item.owner_id.def_id), SupertraitAsDerefTarget { t, - target_principal: target_principal.to_string(), + target_principal, label, }); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 2e447b900e117..94a43ab0c4674 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -8,7 +8,7 @@ use rustc_errors::{ }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::{Predicate, Ty, TyCtxt}; +use rustc_middle::ty::{PolyExistentialTraitRef, Predicate, Ty, TyCtxt}; use rustc_session::parse::ParseSess; use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol}; @@ -556,8 +556,7 @@ pub struct BuiltinUnexpectedCliConfigValue { #[diag(lint_supertrait_as_deref_target)] pub struct SupertraitAsDerefTarget<'a> { pub t: Ty<'a>, - pub target_principal: String, - // pub target_principal: Binder<'a, ExistentialTraitRef<'b>>, + pub target_principal: PolyExistentialTraitRef<'a>, #[subdiagnostic] pub label: Option, } diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index b96d07e7dc831..c59704fc0238f 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -3,6 +3,7 @@ use crate::ty; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_hir::{ItemLocalId, OwnerId}; use rustc_macros::HashStable; @@ -13,6 +14,7 @@ pub enum ResolvedArg { EarlyBound(/* decl */ DefId), LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId), Free(DefId, /* lifetime decl */ DefId), + Error(ErrorGuaranteed), } /// A set containing, at most, one known element. diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 08e2ef0cadab7..884ae7f5da284 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -149,6 +149,9 @@ impl<'tcx> Const<'tcx> { ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)), ty, )), + Some(rbv::ResolvedArg::Error(guar)) => { + Some(tcx.const_error_with_guaranteed(ty, guar)) + } arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id), } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8d2712b6c87e4..f8d17433cf770 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -933,6 +933,12 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { } } +impl rustc_errors::IntoDiagnosticArg for PolyExistentialTraitRef<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable)] pub enum BoundVariableKind { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index bd998ed91d977..37449aaabed8b 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -200,16 +200,21 @@ impl<'a> StringReader<'a> { }; token::Literal(token::Lit { kind, symbol, suffix }) } - rustc_lexer::TokenKind::Lifetime { starts_with_number } => { + rustc_lexer::TokenKind::Lifetime { starts_with_number, contains_emoji } => { // Include the leading `'` in the real identifier, for macro // expansion purposes. See #12512 for the gory details of why // this is necessary. let lifetime_name = self.str_from(start); if starts_with_number { let span = self.mk_sp(start, self.pos); - let mut diag = self.sess.struct_err("lifetimes cannot start with a number"); + let mut diag = self.sess.struct_err("lifetimes or labels cannot start with a number"); diag.set_span(span); diag.stash(span, StashKey::LifetimeIsChar); + } else if contains_emoji { + let span = self.mk_sp(start, self.pos); + let mut diag = self.sess.struct_err("lifetimes or labels cannot contain emojis"); + diag.set_span(span); + diag.stash(span, StashKey::LifetimeContainsEmoji); } let ident = Symbol::intern(lifetime_name); token::Lifetime(ident) diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 57217fb681a97..53e04bcc132a0 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -19,7 +19,6 @@ use rustc_data_structures::sync::Lock; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError}; use rustc_session::Session; use rustc_span::{Span, DUMMY_SP}; -use std::borrow::Borrow; use std::cell::Cell; use std::collections::hash_map::Entry; use std::fmt::Debug; @@ -364,25 +363,13 @@ where let (result, dep_node_index) = execute_job::(qcx, key.clone(), dep_node, job.id); if Q::FEEDABLE { - // We may have put a value inside the cache from inside the execution. - // Verify that it has the same hash as what we have now, to ensure consistency. + // We should not compute queries that also got a value via feeding. + // This can't happen, as query feeding adds the very dependencies to the fed query + // as its feeding query had. So if the fed query is red, so is its feeder, which will + // get evaluated first, and re-feed the query. if let Some((cached_result, _)) = cache.lookup(&key) { - let hasher = Q::HASH_RESULT.expect("feedable forbids no_hash"); - - let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| { - hasher(&mut hcx, cached_result.borrow()) - }); - let new_hash = qcx - .dep_context() - .with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result)); - debug_assert_eq!( - old_hash, - new_hash, - "Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}", - Q::DEP_KIND, - key, - result, - cached_result, + panic!( + "fed query later has its value computed. The already cached value: {cached_result:?}" ); } } diff --git a/src/tools/cargo b/src/tools/cargo index 39c13e67a5962..17b3d0de0897e 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 39c13e67a5962466cc7253d41bc1099bbcb224c3 +Subproject commit 17b3d0de0897e1c6b8ca347bd39f850bb0a5b9f6 diff --git a/tests/ui/bounds-lifetime.stderr b/tests/ui/bounds-lifetime.stderr index a3427e21cde2d..f0bfe784cccc9 100644 --- a/tests/ui/bounds-lifetime.stderr +++ b/tests/ui/bounds-lifetime.stderr @@ -22,7 +22,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | type D = for<'a, T> fn(); | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error[E0658]: only lifetime parameters can be used in this context @@ -31,7 +31,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | type E = dyn for Fn(); | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to 5 previous errors diff --git a/tests/ui/closures/binder/const-bound.rs b/tests/ui/closures/binder/const-bound.rs new file mode 100644 index 0000000000000..b1c79db137510 --- /dev/null +++ b/tests/ui/closures/binder/const-bound.rs @@ -0,0 +1,7 @@ +#![feature(closure_lifetime_binder, non_lifetime_binders)] +//~^ WARN is incomplete and may not be safe to use + +fn main() { + for || -> () {}; + //~^ ERROR late-bound const parameter not allowed on closures +} diff --git a/tests/ui/closures/binder/const-bound.stderr b/tests/ui/closures/binder/const-bound.stderr new file mode 100644 index 0000000000000..c016465c101ce --- /dev/null +++ b/tests/ui/closures/binder/const-bound.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-bound.rs:1:37 + | +LL | #![feature(closure_lifetime_binder, non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound const parameter not allowed on closures + --> $DIR/const-bound.rs:5:9 + | +LL | for || -> () {}; + | ^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/closures/binder/disallow-const.stderr b/tests/ui/closures/binder/disallow-const.stderr index 9f4deaa774dd7..59f299315f856 100644 --- a/tests/ui/closures/binder/disallow-const.stderr +++ b/tests/ui/closures/binder/disallow-const.stderr @@ -4,7 +4,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | for || -> () {}; | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/closures/binder/disallow-ty.stderr b/tests/ui/closures/binder/disallow-ty.stderr index 22882ca2ba67a..3370e21bd711a 100644 --- a/tests/ui/closures/binder/disallow-ty.stderr +++ b/tests/ui/closures/binder/disallow-ty.stderr @@ -4,7 +4,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | for || -> () {}; | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/closures/binder/type-bound-2.rs b/tests/ui/closures/binder/type-bound-2.rs new file mode 100644 index 0000000000000..f4edcdaa9ca9f --- /dev/null +++ b/tests/ui/closures/binder/type-bound-2.rs @@ -0,0 +1,7 @@ +#![feature(closure_lifetime_binder, non_lifetime_binders)] +//~^ WARN is incomplete and may not be safe to use + +fn main() { + for || -> () {}; + //~^ ERROR late-bound type parameter not allowed on closures +} diff --git a/tests/ui/closures/binder/type-bound-2.stderr b/tests/ui/closures/binder/type-bound-2.stderr new file mode 100644 index 0000000000000..14b2dbf03957f --- /dev/null +++ b/tests/ui/closures/binder/type-bound-2.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/type-bound-2.rs:1:37 + | +LL | #![feature(closure_lifetime_binder, non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound type parameter not allowed on closures + --> $DIR/type-bound-2.rs:5:9 + | +LL | for || -> () {}; + | ^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/closures/binder/type-bound.rs b/tests/ui/closures/binder/type-bound.rs new file mode 100644 index 0000000000000..59a3353f4965e --- /dev/null +++ b/tests/ui/closures/binder/type-bound.rs @@ -0,0 +1,7 @@ +#![feature(closure_lifetime_binder, non_lifetime_binders)] +//~^ WARN is incomplete and may not be safe to use + +fn main() { + for || -> T {}; + //~^ ERROR late-bound type parameter not allowed on closures +} diff --git a/tests/ui/closures/binder/type-bound.stderr b/tests/ui/closures/binder/type-bound.stderr new file mode 100644 index 0000000000000..ef00a2dffceae --- /dev/null +++ b/tests/ui/closures/binder/type-bound.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/type-bound.rs:1:37 + | +LL | #![feature(closure_lifetime_binder, non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound type parameter not allowed on closures + --> $DIR/type-bound.rs:5:9 + | +LL | for || -> T {}; + | ^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr index 69b0f74115684..f733c09c22e6b 100644 --- a/tests/ui/conditional-compilation/cfg-generic-params.stderr +++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr @@ -34,7 +34,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn(); | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error[E0658]: only lifetime parameters can be used in this context @@ -43,7 +43,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy; | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error[E0658]: only lifetime parameters can be used in this context @@ -52,7 +52,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to 8 previous errors diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr index 75645e324017d..01c8ee30c5f56 100644 --- a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr +++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr @@ -4,7 +4,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | fn foo() where for T:, {} | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr index d605c9e0df7e4..765ea9f785403 100644 --- a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr +++ b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr @@ -4,7 +4,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | fn a() where for T: Copy {} | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error[E0658]: only lifetime parameters can be used in this context @@ -13,7 +13,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | fn b() where for [(); C]: Copy {} | ^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/tests/ui/lexer/issue-108019-bad-emoji-recovery.rs b/tests/ui/lexer/issue-108019-bad-emoji-recovery.rs new file mode 100644 index 0000000000000..f0f8622456010 --- /dev/null +++ b/tests/ui/lexer/issue-108019-bad-emoji-recovery.rs @@ -0,0 +1,45 @@ +#![allow(unused_labels)] + +// FIXME(#108019): outdated Unicode table +// fn foo() { +// '🥺 loop { +// break +// } +// } + +fn bar() { + '🐱 loop { + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR lifetimes or labels cannot contain emojis + break + } +} + +fn qux() { + 'a🐱 loop { + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR lifetimes or labels cannot contain emojis + break + } +} + +fn quux() { + '1🐱 loop { + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR lifetimes or labels cannot start with a number + break + } +} + +fn x<'🐱>() -> &'🐱 () { + //~^ ERROR lifetimes or labels cannot contain emojis + //~| ERROR lifetimes or labels cannot contain emojis + &() +} + +fn y() { + 'a🐱: loop {} + //~^ ERROR lifetimes or labels cannot contain emojis +} + +fn main() {} diff --git a/tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr b/tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr new file mode 100644 index 0000000000000..be77ffdea349f --- /dev/null +++ b/tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr @@ -0,0 +1,86 @@ +error: labeled expression must be followed by `:` + --> $DIR/issue-108019-bad-emoji-recovery.rs:11:5 + | +LL | '🐱 loop { + | ^--- help: add `:` after the label + | | + | _____the label + | | +LL | | +LL | | +LL | | break +LL | | } + | |_____^ + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: labeled expression must be followed by `:` + --> $DIR/issue-108019-bad-emoji-recovery.rs:19:5 + | +LL | 'a🐱 loop { + | ^---- help: add `:` after the label + | | + | _____the label + | | +LL | | +LL | | +LL | | break +LL | | } + | |_____^ + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: labeled expression must be followed by `:` + --> $DIR/issue-108019-bad-emoji-recovery.rs:27:5 + | +LL | '1🐱 loop { + | ^---- help: add `:` after the label + | | + | _____the label + | | +LL | | +LL | | +LL | | break +LL | | } + | |_____^ + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:11:5 + | +LL | '🐱 loop { + | ^^^ + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:19:5 + | +LL | 'a🐱 loop { + | ^^^^ + +error: lifetimes or labels cannot start with a number + --> $DIR/issue-108019-bad-emoji-recovery.rs:27:5 + | +LL | '1🐱 loop { + | ^^^^ + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:34:6 + | +LL | fn x<'🐱>() -> &'🐱 () { + | ^^^ + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:34:16 + | +LL | fn x<'🐱>() -> &'🐱 () { + | ^^^ + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:41:5 + | +LL | 'a🐱: loop {} + | ^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/issue-108155.rs b/tests/ui/lint/issue-108155.rs new file mode 100644 index 0000000000000..4ae0cbd92ff16 --- /dev/null +++ b/tests/ui/lint/issue-108155.rs @@ -0,0 +1,15 @@ +// check-pass +// check that `deref_into_dyn_supertrait` doesn't cause ICE by eagerly converting +// a cancelled lint + +#![allow(deref_into_dyn_supertrait)] + +trait Trait {} +impl std::ops::Deref for dyn Trait + Send + Sync { + type Target = dyn Trait; + fn deref(&self) -> &Self::Target { + self + } +} + +fn main() {} diff --git a/tests/ui/parser/numeric-lifetime.rs b/tests/ui/parser/numeric-lifetime.rs index 2d82354c62cca..a082a8a44df2a 100644 --- a/tests/ui/parser/numeric-lifetime.rs +++ b/tests/ui/parser/numeric-lifetime.rs @@ -1,6 +1,6 @@ struct S<'1> { s: &'1 usize } -//~^ ERROR lifetimes cannot start with a number -//~| ERROR lifetimes cannot start with a number +//~^ ERROR lifetimes or labels cannot start with a number +//~| ERROR lifetimes or labels cannot start with a number fn main() { // verify that the parse error doesn't stop type checking let x: usize = ""; diff --git a/tests/ui/parser/numeric-lifetime.stderr b/tests/ui/parser/numeric-lifetime.stderr index 7c1bcb7263171..66e35dca92319 100644 --- a/tests/ui/parser/numeric-lifetime.stderr +++ b/tests/ui/parser/numeric-lifetime.stderr @@ -6,13 +6,13 @@ LL | let x: usize = ""; | | | expected due to this -error: lifetimes cannot start with a number +error: lifetimes or labels cannot start with a number --> $DIR/numeric-lifetime.rs:1:10 | LL | struct S<'1> { s: &'1 usize } | ^^ -error: lifetimes cannot start with a number +error: lifetimes or labels cannot start with a number --> $DIR/numeric-lifetime.rs:1:20 | LL | struct S<'1> { s: &'1 usize } diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr index fddc5d9fc2548..0fd16c5d0ee04 100644 --- a/tests/ui/traits/non_lifetime_binders/basic.stderr +++ b/tests/ui/traits/non_lifetime_binders/basic.stderr @@ -4,7 +4,7 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr index ba5953193a47b..c3f4fd6a88e4d 100644 --- a/tests/ui/traits/non_lifetime_binders/fail.stderr +++ b/tests/ui/traits/non_lifetime_binders/fail.stderr @@ -4,7 +4,7 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `T: Trait` is not satisfied diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr index 44071107de411..95656f99976ff 100644 --- a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr +++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr @@ -4,7 +4,7 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default error: late-bound type parameter not allowed on trait object types diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr index bb7dccaf07d5f..3b17f7697b2be 100644 --- a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr +++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr @@ -4,7 +4,7 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #1 for more information + = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default error: late-bound type parameter not allowed on function pointer types