diff --git a/Cargo.lock b/Cargo.lock index 34a33eca3f40b..8391cba278631 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -412,9 +412,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fde55d2a2bfaa4c9668bbc63f531fbdeee3ffe188f4662511ce2c22b3eedebe" +checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518" dependencies = [ "jobserver", ] @@ -1576,9 +1576,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.71" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" +checksum = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9" dependencies = [ "rustc-std-workspace-core", ] diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 737176c48f878..c1e56347ab1e0 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1239,7 +1239,7 @@ impl<'a> Builder<'a> { && self.config.control_flow_guard && compiler.stage >= 1 { - rustflags.arg("-Zcontrol-flow-guard"); + rustflags.arg("-Ccontrol-flow-guard"); } // For `cargo doc` invocations, make rustdoc print the Rust version into the docs diff --git a/src/doc/book b/src/doc/book index 84a31397b34f9..a914f2c7e5cdb 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 84a31397b34f9d405df44f2899ff17a4828dba18 +Subproject commit a914f2c7e5cdb771fa465de142381a51c53b580e diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 82bec5877c77c..bd6e4a9f59c5c 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 82bec5877c77cfad530ca11095db4456d757f668 +Subproject commit bd6e4a9f59c5c1545f572266af77f5c7a5bad6d1 diff --git a/src/doc/reference b/src/doc/reference index 0ea7bc494f128..b329ce3742487 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 0ea7bc494f1289234d8800bb9185021e0ad946f0 +Subproject commit b329ce37424874ad4db94f829a55807c6e21d2cb diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 0b4bb05c1db23..35904e15d3fee 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -42,6 +42,18 @@ generated code, but may be slower to compile. The default value, if not specified, is 16 for non-incremental builds. For incremental builds the default is 256 which allows caching to be more granular. +## control-flow-guard + +This flag controls whether LLVM enables the Windows [Control Flow +Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) +platform security feature. This flag is currently ignored for non-Windows targets. +It takes one of the following values: + +* `y`, `yes`, `on`, `checks`, or no value: enable Control Flow Guard. +* `nochecks`: emit Control Flow Guard metadata without runtime enforcement checks (this +should only be used for testing purposes as it does not provide security enforcement). +* `n`, `no`, `off`: do not enable Control Flow Guard (the default). + ## debug-assertions This flag lets you turn `cfg(debug_assertions)` [conditional diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index d58aad340a1dc..8a1bb258d4274 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -1330,7 +1330,12 @@ impl Builder<'a, 'll, 'tcx> { self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None); } - fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value { + pub(crate) fn phi( + &mut self, + ty: &'ll Type, + vals: &[&'ll Value], + bbs: &[&'ll BasicBlock], + ) -> &'ll Value { assert_eq!(vals.len(), bbs.len()); let phi = unsafe { llvm::LLVMBuildPhi(self.llbuilder, ty, UNNAMED) }; unsafe { diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 21ba97d15a485..a07f6c64edcb1 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -190,7 +190,7 @@ pub unsafe fn create_module( // Control Flow Guard is currently only supported by the MSVC linker on Windows. if sess.target.target.options.is_like_msvc { - match sess.opts.debugging_opts.control_flow_guard { + match sess.opts.cg.control_flow_guard { CFGuard::Disabled => {} CFGuard::NoChecks => { // Set `cfguard=1` module flag to emit metadata only. diff --git a/src/librustc_codegen_llvm/va_arg.rs b/src/librustc_codegen_llvm/va_arg.rs index 8bc3579800ea8..54efa05aee81e 100644 --- a/src/librustc_codegen_llvm/va_arg.rs +++ b/src/librustc_codegen_llvm/va_arg.rs @@ -3,8 +3,9 @@ use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; use rustc_codegen_ssa::mir::operand::OperandRef; -use rustc_codegen_ssa::traits::{ - BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods, +use rustc_codegen_ssa::{ + common::IntPredicate, + traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods}, }; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::Ty; @@ -89,6 +90,81 @@ fn emit_ptr_va_arg( } } +fn emit_aapcs_va_arg( + bx: &mut Builder<'a, 'll, 'tcx>, + list: OperandRef<'tcx, &'ll Value>, + target_ty: Ty<'tcx>, +) -> &'ll Value { + // Implementation of the AAPCS64 calling convention for va_args see + // https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst + let va_list_addr = list.immediate(); + let layout = bx.cx.layout_of(target_ty); + + let mut maybe_reg = bx.build_sibling_block("va_arg.maybe_reg"); + let mut in_reg = bx.build_sibling_block("va_arg.in_reg"); + let mut on_stack = bx.build_sibling_block("va_arg.on_stack"); + let mut end = bx.build_sibling_block("va_arg.end"); + let zero = bx.const_i32(0); + let offset_align = Align::from_bytes(4).unwrap(); + assert!(&*bx.tcx().sess.target.target.target_endian == "little"); + + let gr_type = target_ty.is_any_ptr() || target_ty.is_integral(); + let (reg_off, reg_top_index, slot_size) = if gr_type { + let gr_offs = bx.struct_gep(va_list_addr, 7); + let nreg = (layout.size.bytes() + 7) / 8; + (gr_offs, 3, nreg * 8) + } else { + let vr_off = bx.struct_gep(va_list_addr, 9); + let nreg = (layout.size.bytes() + 15) / 16; + (vr_off, 5, nreg * 16) + }; + + // if the offset >= 0 then the value will be on the stack + let mut reg_off_v = bx.load(reg_off, offset_align); + let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero); + bx.cond_br(use_stack, &on_stack.llbb(), &maybe_reg.llbb()); + + // The value at this point might be in a register, but there is a chance that + // it could be on the stack so we have to update the offset and then check + // the offset again. + + if gr_type && layout.align.abi.bytes() > 8 { + reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(15)); + reg_off_v = maybe_reg.and(reg_off_v, bx.const_i32(-16)); + } + let new_reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(slot_size as i32)); + + maybe_reg.store(new_reg_off_v, reg_off, offset_align); + + // Check to see if we have overflowed the registers as a result of this. + // If we have then we need to use the stack for this value + let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero); + maybe_reg.cond_br(use_stack, &on_stack.llbb(), &in_reg.llbb()); + + let top = in_reg.struct_gep(va_list_addr, reg_top_index); + let top = in_reg.load(top, bx.tcx().data_layout.pointer_align.abi); + + // reg_value = *(@top + reg_off_v); + let top = in_reg.gep(top, &[reg_off_v]); + let top = in_reg.bitcast(top, bx.cx.type_ptr_to(layout.llvm_type(bx))); + let reg_value = in_reg.load(top, layout.align.abi); + in_reg.br(&end.llbb()); + + // On Stack block + let stack_value = + emit_ptr_va_arg(&mut on_stack, list, target_ty, false, Align::from_bytes(8).unwrap(), true); + on_stack.br(&end.llbb()); + + let val = end.phi( + layout.immediate_llvm_type(bx), + &[reg_value, stack_value], + &[&in_reg.llbb(), &on_stack.llbb()], + ); + + *bx = end; + val +} + pub(super) fn emit_va_arg( bx: &mut Builder<'a, 'll, 'tcx>, addr: OperandRef<'tcx, &'ll Value>, @@ -115,6 +191,7 @@ pub(super) fn emit_va_arg( ("aarch64", _) if target.target_os == "ios" => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true) } + ("aarch64", _) => emit_aapcs_va_arg(bx, addr, target_ty), // Windows x86_64 ("x86_64", true) => { let target_ty_size = bx.cx.size_of(target_ty).bytes(); diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 2d65282ce7798..7c153ba0d60cb 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1700,7 +1700,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( } // OBJECT-FILES-NO, AUDIT-ORDER - if sess.opts.debugging_opts.control_flow_guard != CFGuard::Disabled { + if sess.opts.cg.control_flow_guard != CFGuard::Disabled { cmd.control_flow_guard(); } diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 279c65ce03d2d..72302962d8603 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -633,4 +633,5 @@ E0771: include_str!("./error_codes/E0771.md"), E0755, // `#[ffi_pure]` is only allowed on foreign functions E0756, // `#[ffi_const]` is only allowed on foreign functions E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]` + E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`. } diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index f56522406b0a7..6474dc318d329 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -2198,7 +2198,17 @@ pub enum IsAsync { NotAsync, } -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] +#[derive( + Copy, + Clone, + PartialEq, + RustcEncodable, + RustcDecodable, + Debug, + HashStable_Generic, + Eq, + Hash +)] pub enum Defaultness { Default { has_value: bool }, Final, diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 3b564e03d9a94..c63464e5baec9 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -36,12 +36,13 @@ use crate::traits::{Obligation, PredicateObligations}; use rustc_ast::ast; use rustc_hir::def_id::DefId; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{IntType, UintType}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::DUMMY_SP; #[derive(Clone)] pub struct CombineFields<'infcx, 'tcx> { @@ -367,10 +368,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { }; debug!("generalize: for_universe = {:?}", for_universe); + debug!("generalize: trace = {:?}", self.trace); let mut generalize = Generalizer { infcx: self.infcx, - span: self.trace.cause.span, + cause: &self.trace.cause, for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid), for_universe, ambient_variance, @@ -414,7 +416,7 @@ struct Generalizer<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, /// The span, used when creating new type variables and things. - span: Span, + cause: &'cx ObligationCause<'tcx>, /// The vid of the type variable that is in the process of being /// instantiated; if we find this within the type we are folding, @@ -639,7 +641,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { // FIXME: This is non-ideal because we don't give a // very descriptive origin for this region variable. - Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe)) + Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe)) } fn consts( diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 633589db2704c..ff905faa95a9f 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -2010,7 +2010,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::MiscVariable(_) => String::new(), infer::PatternRegion(_) => " for pattern".to_string(), infer::AddrOfRegion(_) => " for borrow expression".to_string(), - infer::Autoref(_) => " for autoref".to_string(), + infer::Autoref(_, _) => " for autoref".to_string(), infer::Coercion(_) => " for automatic coercion".to_string(), infer::LateBoundRegion(_, br, infer::FnCall) => { format!(" for lifetime parameter {}in function call", br_string(br)) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index b6e971feb0e5f..4fa6d9d239424 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -2,227 +2,504 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; -use rustc_errors::{struct_span_err, Applicability, ErrorReported}; -use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind}; -use rustc_middle::ty::RegionKind; +use crate::infer::{SubregionOrigin, TypeTrace}; +use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; +use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; +use rustc_hir::{ + self as hir, GenericBound, ImplItem, Item, ItemKind, Lifetime, LifetimeName, Node, TraitItem, + TyKind, +}; +use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor}; +use rustc_span::symbol::Ident; +use rustc_span::{MultiSpan, Span}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { - /// Print the error message for lifetime errors when the return type is a static impl Trait. + /// Print the error message for lifetime errors when the return type is a static `impl Trait`, + /// `dyn Trait` or if a method call on a trait object introduces a static requirement. pub(super) fn try_report_static_impl_trait(&self) -> Option { debug!("try_report_static_impl_trait(error={:?})", self.error); - if let Some(RegionResolutionError::SubSupConflict( - _, - var_origin, - ref sub_origin, - sub_r, - ref sup_origin, - sup_r, - )) = self.error - { - debug!( - "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})", - var_origin, sub_origin, sub_r, sup_origin, sup_r - ); - let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; - debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup); - let fn_returns = self.tcx().return_type_impl_or_dyn_traits(anon_reg_sup.def_id); - if fn_returns.is_empty() { + let tcx = self.tcx(); + let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? { + RegionResolutionError::SubSupConflict( + _, + var_origin, + sub_origin, + sub_r, + sup_origin, + sup_r, + ) if **sub_r == RegionKind::ReStatic => { + (var_origin, sub_origin, sub_r, sup_origin, sup_r) + } + RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(box TypeTrace { cause, .. }), + sub_r, + sup_r, + ) if **sub_r == RegionKind::ReStatic => { + // This is for an implicit `'static` requirement coming from `impl dyn Trait {}`. + if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + let param = self.find_param_with_region(sup_r, sub_r)?; + let lifetime = if sup_r.has_name() { + format!("lifetime `{}`", sup_r) + } else { + "an anonymous lifetime `'_`".to_string() + }; + let mut err = struct_span_err!( + tcx.sess, + cause.span, + E0772, + "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ + requirement", + param + .param + .pat + .simple_ident() + .map(|s| format!("`{}`", s)) + .unwrap_or_else(|| "`fn` parameter".to_string()), + lifetime, + ctxt.assoc_item.ident, + ); + err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); + err.span_label( + cause.span, + &format!( + "...is captured and required to live as long as `'static` here \ + because of an implicit lifetime bound on the {}", + match ctxt.assoc_item.container { + AssocItemContainer::TraitContainer(id) => + format!("`impl` of `{}`", tcx.def_path_str(id)), + AssocItemContainer::ImplContainer(_) => + "inherent `impl`".to_string(), + }, + ), + ); + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { + err.emit(); + return Some(ErrorReported); + } else { + err.cancel(); + } + } return None; } - debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); - if *sub_r == RegionKind::ReStatic { - let sp = var_origin.span(); - let return_sp = sub_origin.span(); - let param_info = self.find_param_with_region(sup_r, sub_r)?; - let (lifetime_name, lifetime) = if sup_r.has_name() { - (sup_r.to_string(), format!("lifetime `{}`", sup_r)) - } else { - ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) - }; - let mut err = struct_span_err!( - self.tcx().sess, - sp, - E0759, - "cannot infer an appropriate lifetime" - ); + _ => return None, + }; + debug!( + "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})", + var_origin, sub_origin, sub_r, sup_origin, sup_r + ); + let anon_reg_sup = tcx.is_suitable_region(sup_r)?; + debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup); + let sp = var_origin.span(); + let return_sp = sub_origin.span(); + let param = self.find_param_with_region(sup_r, sub_r)?; + let (lifetime_name, lifetime) = if sup_r.has_name() { + (sup_r.to_string(), format!("lifetime `{}`", sup_r)) + } else { + ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) + }; + let param_name = param + .param + .pat + .simple_ident() + .map(|s| format!("`{}`", s)) + .unwrap_or_else(|| "`fn` parameter".to_string()); + let mut err = struct_span_err!( + tcx.sess, + sp, + E0759, + "{} has {} but it needs to satisfy a `'static` lifetime requirement", + param_name, + lifetime, + ); + err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); + debug!("try_report_static_impl_trait: param_info={:?}", param); + + // We try to make the output have fewer overlapping spans if possible. + if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) + && sup_origin.span() != return_sp + { + // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs` + + // Customize the spans and labels depending on their relative order so + // that split sentences flow correctly. + if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() { + // Avoid the following: + // + // error: cannot infer an appropriate lifetime + // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + // | + // LL | fn foo(x: &i32) -> Box { Box::new(x) } + // | ---- ---------^- + // + // and instead show: + // + // error: cannot infer an appropriate lifetime + // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + // | + // LL | fn foo(x: &i32) -> Box { Box::new(x) } + // | ---- ^ err.span_label( - param_info.param_ty_span, - &format!("this data with {}...", lifetime), + sup_origin.span(), + "...is captured here, requiring it to live as long as `'static`", ); - debug!("try_report_static_impl_trait: param_info={:?}", param_info); + } else { + err.span_label(sup_origin.span(), "...is captured here..."); + if return_sp < sup_origin.span() { + err.span_note( + return_sp, + "...and is required to live as long as `'static` here", + ); + } else { + err.span_label( + return_sp, + "...and is required to live as long as `'static` here", + ); + } + } + } else { + err.span_label( + return_sp, + "...is captured and required to live as long as `'static` here", + ); + } + + let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); - // We try to make the output have fewer overlapping spans if possible. - if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) - && sup_origin.span() != return_sp + let mut override_error_code = None; + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { + if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a + // `'static` lifetime when called as a method on a binding: `bar.qux()`. + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { + override_error_code = Some(ctxt.assoc_item.ident); + } + } + } + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin { + if let ObligationCauseCode::ItemObligation(item_def_id) = cause.code { + // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static` + // lifetime as above, but called using a fully-qualified path to the method: + // `Foo::qux(bar)`. + let mut v = TraitObjectVisitor(vec![]); + v.visit_ty(param.param_ty); + if let Some((ident, self_ty)) = + self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0[..]) { - // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs` - - // Customize the spans and labels depending on their relative order so - // that split sentences flow correctly. - if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() { - // Avoid the following: - // - // error: cannot infer an appropriate lifetime - // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 - // | - // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ---------^- - // - // and instead show: - // - // error: cannot infer an appropriate lifetime - // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 - // | - // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ^ - err.span_label( - sup_origin.span(), - "...is captured here, requiring it to live as long as `'static`", + if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0[..], ident, self_ty) + { + override_error_code = Some(ident); + } + } + } + } + if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) { + // Provide a more targetted error code and description. + err.code(rustc_errors::error_code!(E0772)); + err.set_primary_message(&format!( + "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ + requirement", + param_name, lifetime, ident, + )); + } + + debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); + // FIXME: account for the need of parens in `&(dyn Trait + '_)` + let consider = "consider changing the"; + let declare = "to declare that the"; + let arg = match param.param.pat.simple_ident() { + Some(simple_ident) => format!("argument `{}`", simple_ident), + None => "the argument".to_string(), + }; + let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); + let explicit_static = format!("explicit `'static` bound to the lifetime of {}", arg); + let captures = format!("captures data from {}", arg); + let add_static_bound = "alternatively, add an explicit `'static` bound to this reference"; + let plus_lt = format!(" + {}", lifetime_name); + for fn_return in fn_returns { + if fn_return.span.desugaring_kind().is_some() { + // Skip `async` desugaring `impl Future`. + continue; + } + match fn_return.kind { + TyKind::OpaqueDef(item_id, _) => { + let item = tcx.hir().item(item_id.id); + let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind { + opaque + } else { + err.emit(); + return Some(ErrorReported); + }; + + if let Some(span) = opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { + name: LifetimeName::Static, + span, + .. + }) => Some(*span), + _ => None, + }) + .next() + { + err.span_suggestion_verbose( + span, + &format!("{} `impl Trait`'s {}", consider, explicit_static), + lifetime_name.clone(), + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param.param_ty_span, + add_static_bound, + param.param_ty.to_string(), + Applicability::MaybeIncorrect, ); + } else if let Some(_) = opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { name, span, .. }) + if name.ident().to_string() == lifetime_name => + { + Some(*span) + } + _ => None, + }) + .next() + { } else { - err.span_label(sup_origin.span(), "...is captured here..."); - if return_sp < sup_origin.span() { - err.span_note( - return_sp, - "...and is required to live as long as `'static` here", - ); - } else { - err.span_label( - return_sp, - "...and is required to live as long as `'static` here", - ); - } + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "{declare} `impl Trait` {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, + ), + plus_lt.clone(), + Applicability::MaybeIncorrect, + ); } - } else { - err.span_label( - return_sp, - "...is captured and required to live as long as `'static` here", - ); } + TyKind::TraitObject(_, lt) => match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "{declare} trait object {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, + ), + plus_lt.clone(), + Applicability::MaybeIncorrect, + ); + } + name if name.ident().to_string() != lifetime_name => { + // With this check we avoid suggesting redundant bounds. This + // would happen if there are nested impl/dyn traits and only + // one of them has the bound we'd suggest already there, like + // in `impl Foo + '_`. + err.span_suggestion_verbose( + lt.span, + &format!("{} trait object's {}", consider, explicit_static), + lifetime_name.clone(), + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param.param_ty_span, + add_static_bound, + param.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } + _ => {} + }, + _ => {} + } + } + err.emit(); + Some(ErrorReported) + } - // FIXME: account for the need of parens in `&(dyn Trait + '_)` - let consider = "consider changing the"; - let declare = "to declare that the"; - let arg = match param_info.param.pat.simple_ident() { - Some(simple_ident) => format!("argument `{}`", simple_ident), - None => "the argument".to_string(), - }; - let explicit = - format!("you can add an explicit `{}` lifetime bound", lifetime_name); - let explicit_static = - format!("explicit `'static` bound to the lifetime of {}", arg); - let captures = format!("captures data from {}", arg); - let add_static_bound = - "alternatively, add an explicit `'static` bound to this reference"; - let plus_lt = format!(" + {}", lifetime_name); - for fn_return in fn_returns { - if fn_return.span.desugaring_kind().is_some() { - // Skip `async` desugaring `impl Future`. - continue; + fn get_impl_ident_and_self_ty_from_trait( + &self, + def_id: DefId, + trait_objects: &[DefId], + ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { + let tcx = self.tcx(); + match tcx.hir().get_if_local(def_id) { + Some(Node::ImplItem(ImplItem { ident, hir_id, .. })) => { + match tcx.hir().find(tcx.hir().get_parent_item(*hir_id)) { + Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) => { + Some((*ident, self_ty)) } - match fn_return.kind { - TyKind::OpaqueDef(item_id, _) => { - let item = self.tcx().hir().item(item_id.id); - let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind { - opaque - } else { - err.emit(); - return Some(ErrorReported); - }; - - if let Some(span) = opaque - .bounds - .iter() - .filter_map(|arg| match arg { - GenericBound::Outlives(Lifetime { - name: LifetimeName::Static, - span, + _ => None, + } + } + Some(Node::TraitItem(TraitItem { ident, hir_id, .. })) => { + let parent_id = tcx.hir().get_parent_item(*hir_id); + match tcx.hir().find(parent_id) { + Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { + // The method being called is defined in the `trait`, but the `'static` + // obligation comes from the `impl`. Find that `impl` so that we can point + // at it in the suggestion. + let trait_did = tcx.hir().local_def_id(parent_id).to_def_id(); + match tcx + .hir() + .trait_impls(trait_did) + .iter() + .filter_map(|impl_node| { + let impl_did = tcx.hir().local_def_id(*impl_node); + match tcx.hir().get_if_local(impl_did.to_def_id()) { + Some(Node::Item(Item { + kind: ItemKind::Impl { self_ty, .. }, .. - }) => Some(*span), - _ => None, - }) - .next() - { - err.span_suggestion_verbose( - span, - &format!("{} `impl Trait`'s {}", consider, explicit_static), - lifetime_name.clone(), - Applicability::MaybeIncorrect, - ); - err.span_suggestion_verbose( - param_info.param_ty_span, - add_static_bound, - param_info.param_ty.to_string(), - Applicability::MaybeIncorrect, - ); - } else if let Some(_) = opaque - .bounds - .iter() - .filter_map(|arg| match arg { - GenericBound::Outlives(Lifetime { name, span, .. }) - if name.ident().to_string() == lifetime_name => + })) if trait_objects.iter().all(|did| { + // FIXME: we should check `self_ty` against the receiver + // type in the `UnifyReceiver` context, but for now, use + // this imperfect proxy. This will fail if there are + // multiple `impl`s for the same trait like + // `impl Foo for Box` and `impl Foo for dyn Bar`. + // In that case, only the first one will get suggestions. + let mut hir_v = HirTraitObjectVisitor(vec![], *did); + hir_v.visit_ty(self_ty); + !hir_v.0.is_empty() + }) => { - Some(*span) + Some(self_ty) } _ => None, - }) - .next() - { - } else { - err.span_suggestion_verbose( - fn_return.span.shrink_to_hi(), - &format!( - "{declare} `impl Trait` {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), - plus_lt.clone(), - Applicability::MaybeIncorrect, - ); - } + } + }) + .next() + { + Some(self_ty) => Some((*ident, self_ty)), + _ => None, } - TyKind::TraitObject(_, lt) => match lt.name { - LifetimeName::ImplicitObjectLifetimeDefault => { - err.span_suggestion_verbose( - fn_return.span.shrink_to_hi(), - &format!( - "{declare} trait object {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), - plus_lt.clone(), - Applicability::MaybeIncorrect, - ); - } - name if name.ident().to_string() != lifetime_name => { - // With this check we avoid suggesting redundant bounds. This - // would happen if there are nested impl/dyn traits and only - // one of them has the bound we'd suggest already there, like - // in `impl Foo + '_`. - err.span_suggestion_verbose( - lt.span, - &format!("{} trait object's {}", consider, explicit_static), - lifetime_name.clone(), - Applicability::MaybeIncorrect, - ); - err.span_suggestion_verbose( - param_info.param_ty_span, - add_static_bound, - param_info.param_ty.to_string(), - Applicability::MaybeIncorrect, - ); - } - _ => {} - }, - _ => {} + } + _ => None, + } + } + _ => None, + } + } + + /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default + /// `'static` obligation. Suggest relaxing that implicit bound. + fn find_impl_on_dyn_trait( + &self, + err: &mut DiagnosticBuilder<'_>, + ty: Ty<'_>, + ctxt: &UnifyReceiverContext<'tcx>, + ) -> bool { + let tcx = self.tcx(); + + // Find the method being called. + let instance = match ty::Instance::resolve( + tcx, + ctxt.param_env, + ctxt.assoc_item.def_id, + self.infcx.resolve_vars_if_possible(&ctxt.substs), + ) { + Ok(Some(instance)) => instance, + _ => return false, + }; + + let mut v = TraitObjectVisitor(vec![]); + v.visit_ty(ty); + + // Get the `Ident` of the method being called and the corresponding `impl` (to point at + // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called). + let (ident, self_ty) = + match self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0[..]) { + Some((ident, self_ty)) => (ident, self_ty), + None => return false, + }; + + // Find the trait object types in the argument, so we point at *only* the trait object. + self.suggest_constrain_dyn_trait_in_impl(err, &v.0[..], ident, self_ty) + } + + fn suggest_constrain_dyn_trait_in_impl( + &self, + err: &mut DiagnosticBuilder<'_>, + found_dids: &[DefId], + ident: Ident, + self_ty: &hir::Ty<'_>, + ) -> bool { + let mut suggested = false; + for found_did in found_dids { + let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); + hir_v.visit_ty(&self_ty); + for span in &hir_v.0 { + let mut multi_span: MultiSpan = vec![*span].into(); + multi_span.push_span_label( + *span, + "this has an implicit `'static` lifetime requirement".to_string(), + ); + multi_span.push_span_label( + ident.span, + "calling this method introduces the `impl`'s 'static` requirement".to_string(), + ); + err.span_note(multi_span, "the used `impl` has a `'static` requirement"); + err.span_suggestion_verbose( + span.shrink_to_hi(), + "consider relaxing the implicit `'static` requirement", + " + '_".to_string(), + Applicability::MaybeIncorrect, + ); + suggested = true; + } + } + suggested + } +} + +/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime. +struct TraitObjectVisitor(Vec); + +impl TypeVisitor<'_> for TraitObjectVisitor { + fn visit_ty(&mut self, t: Ty<'_>) -> bool { + match t.kind { + ty::Dynamic(preds, RegionKind::ReStatic) => { + if let Some(def_id) = preds.principal_def_id() { + self.0.push(def_id); + } + false + } + _ => t.super_visit_with(self), + } + } +} + +/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime. +struct HirTraitObjectVisitor(Vec, DefId); + +impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor { + type Map = ErasedMap<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { + match t.kind { + TyKind::TraitObject( + poly_trait_refs, + Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. }, + ) => { + for ptr in poly_trait_refs { + if Some(self.1) == ptr.trait_ref.trait_def_id() { + self.0.push(ptr.span); } } - err.emit(); - return Some(ErrorReported); } + _ => {} } - None + walk_ty(self, t); } } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs index fa999abb1a86c..28e9dd90cfd67 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs @@ -7,20 +7,18 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, DefIdTree, Region, Ty}; use rustc_span::Span; -// The struct contains the information about the anonymous region -// we are searching for. +/// Information about the anonymous region we are searching for. #[derive(Debug)] pub(super) struct AnonymousParamInfo<'tcx> { - // the parameter corresponding to the anonymous region + /// The parameter corresponding to the anonymous region. pub param: &'tcx hir::Param<'tcx>, - // the type corresponding to the anonymopus region parameter + /// The type corresponding to the anonymous region parameter. pub param_ty: Ty<'tcx>, - // the ty::BoundRegion corresponding to the anonymous region + /// The ty::BoundRegion corresponding to the anonymous region. pub bound_region: ty::BoundRegion, - // param_ty_span contains span of parameter type + /// The `Span` of the parameter type. pub param_ty_span: Span, - // corresponds to id the argument is the first parameter - // in the declaration + /// Signals that the argument is the first parameter in the declaration. pub is_first: bool, } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 37883fcb07468..3744ad5d0324a 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -463,7 +463,7 @@ pub enum RegionVariableOrigin { AddrOfRegion(Span), /// Regions created as part of an autoref of a method receiver - Autoref(Span), + Autoref(Span, ty::AssocItem), /// Regions created as part of an automatic coercion Coercion(Span), @@ -1800,15 +1800,15 @@ impl<'tcx> SubregionOrigin<'tcx> { impl RegionVariableOrigin { pub fn span(&self) -> Span { match *self { - MiscVariable(a) => a, - PatternRegion(a) => a, - AddrOfRegion(a) => a, - Autoref(a) => a, - Coercion(a) => a, - EarlyBoundRegion(a, ..) => a, - LateBoundRegion(a, ..) => a, + MiscVariable(a) + | PatternRegion(a) + | AddrOfRegion(a) + | Autoref(a, _) + | Coercion(a) + | EarlyBoundRegion(a, ..) + | LateBoundRegion(a, ..) + | UpvarRegion(_, a) => a, BoundRegionInCoherence(_) => rustc_span::DUMMY_SP, - UpvarRegion(_, a) => a, NLL(..) => bug!("NLL variable used with `span`"), } } diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index 0cd6585163c4e..bacb7fa153e43 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -13,6 +13,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(bindings_after_at)] #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index 3c549b8852368..22197a66530dd 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -420,6 +420,7 @@ fn test_codegen_options_tracking_hash() { // Make sure that changing a [TRACKED] option changes the hash. // This list is in alphabetical order. tracked!(code_model, Some(CodeModel::Large)); + tracked!(control_flow_guard, CFGuard::Checks); tracked!(debug_assertions, Some(true)); tracked!(debuginfo, 0xdeadbeef); tracked!(embed_bitcode, false); @@ -537,7 +538,6 @@ fn test_debugging_options_tracking_hash() { tracked!(binary_dep_depinfo, true); tracked!(chalk, true); tracked!(codegen_backend, Some("abc".to_string())); - tracked!(control_flow_guard, CFGuard::Checks); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(debug_macros, true); tracked!(dep_info_omit_d_target, true); diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml index 4fc02e348f646..1a034294cd8eb 100644 --- a/src/librustc_llvm/Cargo.toml +++ b/src/librustc_llvm/Cargo.toml @@ -14,8 +14,8 @@ static-libstdcpp = [] emscripten = [] [dependencies] -libc = "0.2" +libc = "0.2.73" [build-dependencies] build_helper = { path = "../build_helper" } -cc = "1.0.1" +cc = "1.0.58" diff --git a/src/librustc_middle/traits/mod.rs b/src/librustc_middle/traits/mod.rs index c15c31a53f0c9..d2747e5fc659b 100644 --- a/src/librustc_middle/traits/mod.rs +++ b/src/librustc_middle/traits/mod.rs @@ -169,6 +169,13 @@ impl<'tcx> ObligationCause<'tcx> { } } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct UnifyReceiverContext<'tcx> { + pub assoc_item: ty::AssocItem, + pub param_env: ty::ParamEnv<'tcx>, + pub substs: SubstsRef<'tcx>, +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum ObligationCauseCode<'tcx> { /// Not well classified or should be obvious from the span. @@ -300,6 +307,8 @@ pub enum ObligationCauseCode<'tcx> { /// Method receiver MethodReceiver, + UnifyReceiver(Box>), + /// `return` with no expression ReturnNoExpression, diff --git a/src/librustc_middle/traits/structural_impls.rs b/src/librustc_middle/traits/structural_impls.rs index 334462790edbc..18b4371053a89 100644 --- a/src/librustc_middle/traits/structural_impls.rs +++ b/src/librustc_middle/traits/structural_impls.rs @@ -213,12 +213,26 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::StartFunctionType => Some(super::StartFunctionType), super::IntrinsicType => Some(super::IntrinsicType), super::MethodReceiver => Some(super::MethodReceiver), + super::UnifyReceiver(ref ctxt) => tcx.lift(ctxt).map(|ctxt| super::UnifyReceiver(ctxt)), super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), super::TrivialBound => Some(super::TrivialBound), } } } +impl<'a, 'tcx> Lift<'tcx> for traits::UnifyReceiverContext<'a> { + type Lifted = traits::UnifyReceiverContext<'tcx>; + fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { + tcx.lift(&self.param_env).and_then(|param_env| { + tcx.lift(&self.substs).map(|substs| traits::UnifyReceiverContext { + assoc_item: self.assoc_item, + param_env, + substs, + }) + }) + } +} + impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> { type Lifted = traits::DerivedObligationCause<'tcx>; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 51a353c013241..9007bd99d7e4b 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -136,7 +136,7 @@ pub struct ResolverOutputs { pub extern_prelude: FxHashMap, } -#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)] pub enum AssocItemContainer { TraitContainer(DefId), ImplContainer(DefId), @@ -184,7 +184,7 @@ pub enum ImplPolarity { Reservation, } -#[derive(Copy, Clone, Debug, PartialEq, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)] pub struct AssocItem { pub def_id: DefId, #[stable_hasher(project(name))] @@ -199,7 +199,7 @@ pub struct AssocItem { pub fn_has_self_parameter: bool, } -#[derive(Copy, Clone, PartialEq, Debug, HashStable)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)] pub enum AssocKind { Const, Fn, @@ -316,7 +316,7 @@ impl<'tcx> AssociatedItems<'tcx> { } } -#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)] pub enum Visibility { /// Visible everywhere (including in other crates). Public, diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 5836fc9c95a80..29549041d258c 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::{Abi, LayoutOf as _, Primitive, Size}; @@ -54,6 +54,9 @@ crate fn eval_nullary_intrinsic<'tcx>( let name = tcx.item_name(def_id); Ok(match name { sym::type_name => { + if tp_ty.needs_subst() { + throw_inval!(TooGeneric); + } let alloc = type_name::alloc_type_name(tcx, tp_ty); ConstValue::Slice { data: alloc, start: 0, end: alloc.len() } } @@ -68,7 +71,12 @@ crate fn eval_nullary_intrinsic<'tcx>( }; ConstValue::from_machine_usize(n, &tcx) } - sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty)), + sym::type_id => { + if tp_ty.needs_subst() { + throw_inval!(TooGeneric); + } + ConstValue::from_u64(tcx.type_id_hash(tp_ty)) + } sym::variant_count => { if let ty::Adt(ref adt, _) = tp_ty.kind { ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx) diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 839ffa5785ada..620a04b45b0e4 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -103,7 +103,7 @@ pub enum Strip { Symbols, } -/// The different settings that the `-Z control-flow-guard` flag can have. +/// The different settings that the `-C control-flow-guard` flag can have. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum CFGuard { /// Do not emit Control Flow Guard metadata or checks. diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 6b2097240e215..099d11264225e 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -692,6 +692,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "choose the code model to use (`rustc --print code-models` for details)"), codegen_units: Option = (None, parse_opt_uint, [UNTRACKED], "divide crate into N units to optimize in parallel"), + control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED], + "use Windows Control Flow Guard (default: no)"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the `cfg(debug_assertions)` directive"), debuginfo: usize = (0, parse_uint, [TRACKED], @@ -809,8 +811,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "enable the experimental Chalk-based trait solving engine"), codegen_backend: Option = (None, parse_opt_string, [TRACKED], "the backend to use"), - control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED], - "use Windows Control Flow Guard (default: no)"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), debug_macros: bool = (false, parse_bool, [TRACKED], diff --git a/src/librustc_target/spec/aarch64_apple_darwin.rs b/src/librustc_target/spec/aarch64_apple_darwin.rs new file mode 100644 index 0000000000000..60daf10b36afe --- /dev/null +++ b/src/librustc_target/spec/aarch64_apple_darwin.rs @@ -0,0 +1,30 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::apple_base::opts(); + base.cpu = "apple-a12".to_string(); + base.max_atomic_width = Some(128); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]); + + base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); + + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + let arch = "aarch64"; + let llvm_target = super::apple_base::macos_llvm_target(&arch); + + Ok(Target { + llvm_target, + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(), + arch: arch.to_string(), + target_os: "macos".to_string(), + target_env: String::new(), + target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { target_mcount: "\u{1}mcount".to_string(), ..base }, + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index d53033ba3ba20..5a97ef441c203 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -574,6 +574,7 @@ supported_targets! { ("i686-unknown-haiku", i686_unknown_haiku), ("x86_64-unknown-haiku", x86_64_unknown_haiku), + ("aarch64-apple-darwin", aarch64_apple_darwin), ("x86_64-apple-darwin", x86_64_apple_darwin), ("i686-apple-darwin", i686_apple_darwin), diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index 31011e8474958..909aebec70b58 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -5,7 +5,10 @@ pub fn target() -> TargetResult { base.cpu = "core2".to_string(); base.max_atomic_width = Some(128); // core2 support cmpxchg16b base.eliminate_frame_pointer = false; - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); + base.pre_link_args.insert( + LinkerFlavor::Gcc, + vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()], + ); base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); base.stack_probes = true; diff --git a/src/librustc_trait_selection/traits/codegen/mod.rs b/src/librustc_trait_selection/traits/codegen/mod.rs index cf575d3eca9c2..dd7ea55cc1043 100644 --- a/src/librustc_trait_selection/traits/codegen/mod.rs +++ b/src/librustc_trait_selection/traits/codegen/mod.rs @@ -6,6 +6,7 @@ use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::traits::{ FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, + Unimplemented, }; use rustc_errors::ErrorReported; use rustc_middle::ty::fold::TypeFoldable; @@ -58,6 +59,18 @@ pub fn codegen_fulfill_obligation<'tcx>( ); return Err(ErrorReported); } + Err(Unimplemented) => { + // This can trigger when we probe for the source of a `'static` lifetime requirement + // on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound. + infcx.tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + &format!( + "Encountered error `Unimplemented` selecting `{:?}` during codegen", + trait_ref + ), + ); + return Err(ErrorReported); + } Err(e) => { bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 0a6fb72ca51ea..0632ce2319aee 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1706,6 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::IntrinsicType | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression + | ObligationCauseCode::UnifyReceiver(..) | ObligationCauseCode::MiscObligation => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 96248e18aaf87..ed84095ae6b0c 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -6,6 +6,7 @@ use crate::hir::def_id::DefId; use crate::hir::GenericArg; use rustc_hir as hir; use rustc_infer::infer::{self, InferOk}; +use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::fold::TypeFoldable; @@ -91,7 +92,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // signature (which is also done during probing). let method_sig_rcvr = self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]); - self.unify_receivers(self_ty, method_sig_rcvr); + debug!( + "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}", + self_ty, method_sig_rcvr, method_sig, method_predicates + ); + self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs); let (method_sig, method_predicates) = self.normalize_associated_types_in(self.span, &(method_sig, method_predicates)); @@ -150,7 +155,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); if let Some(mutbl) = pick.autoref { - let region = self.next_region_var(infer::Autoref(self.span)); + let region = self.next_region_var(infer::Autoref(self.span, pick.item)); target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target }); let mutbl = match mutbl { hir::Mutability::Not => AutoBorrowMutability::Not, @@ -334,8 +339,26 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ) } - fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) { - match self.at(&self.misc(self.span), self.param_env).sup(method_self_ty, self_ty) { + fn unify_receivers( + &mut self, + self_ty: Ty<'tcx>, + method_self_ty: Ty<'tcx>, + pick: &probe::Pick<'tcx>, + substs: SubstsRef<'tcx>, + ) { + debug!( + "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}", + self_ty, method_self_ty, self.span, pick + ); + let cause = self.cause( + self.span, + ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext { + assoc_item: pick.item, + param_env: self.param_env, + substs, + })), + ); + match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 850a4b3cbc216..d0312d77a7c5d 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1291,6 +1291,16 @@ h4 > .important-traits { /* Media Queries */ +@media (min-width: 701px) { + /* In case there is no documentation before a code block, we need to add some margin at the top + to prevent an overlay between the "collapse toggle" and the information tooltip. + However, it's needed needed with smaller screen width because the doc/code block is always put + "one line" below. */ + .information:first-child > .tooltip { + margin-top: 16px; + } +} + @media (max-width: 700px) { body { padding-top: 0px; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index e187b9251f71e..6f221da1168c6 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1,5 +1,5 @@ use rustc_ast::ast; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_expand::base::SyntaxExtensionKind; use rustc_feature::UnstableFeatures; use rustc_hir as hir; @@ -45,7 +45,17 @@ pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_>) -> Crate { enum ErrorKind { ResolutionFailure, - AnchorFailure(&'static str), + AnchorFailure(AnchorFailure), +} + +enum AnchorFailure { + MultipleAnchors, + Primitive, + Variant, + AssocConstant, + AssocType, + Field, + Method, } struct LinkCollector<'a, 'tcx> { @@ -197,9 +207,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // Not a trait item; just return what we found. Res::PrimTy(..) => { if extra_fragment.is_some() { - return Err(ErrorKind::AnchorFailure( - "primitive types cannot be followed by anchors", - )); + return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive)); } return Ok((res, Some(path_str.to_owned()))); } @@ -209,9 +217,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { if disambiguator == Some("type") { if let Some(prim) = is_primitive(path_str, ns) { if extra_fragment.is_some() { - return Err(ErrorKind::AnchorFailure( - "primitive types cannot be followed by anchors", - )); + return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive)); } return Ok((prim, Some(path_str.to_owned()))); } @@ -228,9 +234,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } } else if let Some(prim) = is_primitive(path_str, ns) { if extra_fragment.is_some() { - return Err(ErrorKind::AnchorFailure( - "primitive types cannot be followed by anchors", - )); + return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive)); } return Ok((prim, Some(path_str.to_owned()))); } else { @@ -338,9 +342,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { }; if extra_fragment.is_some() { Err(ErrorKind::AnchorFailure(if item.kind == ty::AssocKind::Fn { - "methods cannot be followed by anchors" + AnchorFailure::Method } else { - "associated constants cannot be followed by anchors" + AnchorFailure::AssocConstant })) } else { Ok((ty_res, Some(format!("{}.{}", out, item_name)))) @@ -358,9 +362,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } { if extra_fragment.is_some() { Err(ErrorKind::AnchorFailure(if def.is_enum() { - "enum variants cannot be followed by anchors" + AnchorFailure::Variant } else { - "struct fields cannot be followed by anchors" + AnchorFailure::Field })) } else { Ok(( @@ -404,11 +408,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { if extra_fragment.is_some() { Err(ErrorKind::AnchorFailure(if item.kind == ty::AssocKind::Const { - "associated constants cannot be followed by anchors" + AnchorFailure::AssocConstant } else if item.kind == ty::AssocKind::Type { - "associated types cannot be followed by anchors" + AnchorFailure::AssocType } else { - "methods cannot be followed by anchors" + AnchorFailure::Method })) } else { Ok((ty_res, Some(format!("{}.{}", kind, item_name)))) @@ -559,16 +563,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let link = ori_link.replace("`", ""); let parts = link.split('#').collect::>(); let (link, extra_fragment) = if parts.len() > 2 { - build_diagnostic( - cx, - &item, - &link, - &dox, - link_range, - "has an issue with the link anchor.", - "only one `#` is allowed in a link", - None, - ); + anchor_failure(cx, &item, &link, &dox, link_range, AnchorFailure::MultipleAnchors); continue; } else if parts.len() == 2 { if parts[0].trim().is_empty() { @@ -803,21 +798,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { && (item.visibility == Visibility::Public) && !self.cx.render_options.document_private { - let item_name = item.name.as_deref().unwrap_or(""); - let err_msg = format!( - "public documentation for `{}` links to a private item", - item_name - ); - build_diagnostic( - cx, - &item, - path_str, - &dox, - link_range, - &err_msg, - "this item is private", - None, - ); + privacy_error(cx, &item, &path_str, &dox, link_range); continue; } } @@ -851,24 +832,33 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } -fn build_diagnostic( +/// Reports a diagnostic for an intra-doc link. +/// +/// If no link range is provided, or the source span of the link cannot be determined, the span of +/// the entire documentation block is used for the lint. If a range is provided but the span +/// calculation fails, a note is added to the diagnostic pointing to the link in the markdown. +/// +/// The `decorate` callback is invoked in all cases to allow further customization of the +/// diagnostic before emission. If the span of the link was able to be determined, the second +/// parameter of the callback will contain it, and the primary span of the diagnostic will be set +/// to it. +fn report_diagnostic( cx: &DocContext<'_>, + msg: &str, item: &Item, - path_str: &str, dox: &str, link_range: Option>, - err_msg: &str, - short_err_msg: &str, - help_msg: Option<&str>, + decorate: impl FnOnce(&mut DiagnosticBuilder<'_>, Option), ) { let hir_id = match cx.as_local_hir_id(item.def_id) { Some(hir_id) => hir_id, None => { // If non-local, no need to check anything. - info!("ignoring warning from parent crate: {}", err_msg); + info!("ignoring warning from parent crate: {}", msg); return; } }; + let attrs = &item.attrs; let sp = span_of_attrs(attrs).unwrap_or(item.source.span()); @@ -877,12 +867,15 @@ fn build_diagnostic( hir_id, sp, |lint| { - let mut diag = lint.build(&format!("`[{}]` {}", path_str, err_msg)); + let mut diag = lint.build(msg); + + let span = link_range + .as_ref() + .and_then(|range| super::source_span_for_markdown_range(cx, dox, range, attrs)); + if let Some(link_range) = link_range { - if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) - { + if let Some(sp) = span { diag.set_span(sp); - diag.span_label(sp, short_err_msg); } else { // blah blah blah\nblah\nblah [blah] blah blah\nblah blah // ^ ~~~~ @@ -902,20 +895,15 @@ fn build_diagnostic( found = link_range.len(), )); } - }; - if let Some(help_msg) = help_msg { - diag.help(help_msg); } + + decorate(&mut diag, span); + diag.emit(); }, ); } -/// Reports a resolution failure diagnostic. -/// -/// If we cannot find the exact source span of the resolution failure, we use the span of the -/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown -/// line containing the failure as a note as well. fn resolution_failure( cx: &DocContext<'_>, item: &Item, @@ -923,15 +911,19 @@ fn resolution_failure( dox: &str, link_range: Option>, ) { - build_diagnostic( + report_diagnostic( cx, + &format!("unresolved link to `{}`", path_str), item, - path_str, dox, link_range, - "cannot be resolved, ignoring it.", - "cannot be resolved, ignoring", - Some("to escape `[` and `]` characters, just add '\\' before them like `\\[` or `\\]`"), + |diag, sp| { + if let Some(sp) = sp { + diag.span_label(sp, "unresolved link"); + } + + diag.help(r#"to escape `[` and `]` characters, add '\' before them like `\[` or `\]`"#); + }, ); } @@ -941,18 +933,39 @@ fn anchor_failure( path_str: &str, dox: &str, link_range: Option>, - msg: &str, + failure: AnchorFailure, ) { - build_diagnostic( - cx, - item, - path_str, - dox, - link_range, - "has an issue with the link anchor.", - msg, - None, - ); + let msg = match failure { + AnchorFailure::MultipleAnchors => format!("`{}` contains multiple anchors", path_str), + AnchorFailure::Primitive + | AnchorFailure::Variant + | AnchorFailure::AssocConstant + | AnchorFailure::AssocType + | AnchorFailure::Field + | AnchorFailure::Method => { + let kind = match failure { + AnchorFailure::Primitive => "primitive type", + AnchorFailure::Variant => "enum variant", + AnchorFailure::AssocConstant => "associated constant", + AnchorFailure::AssocType => "associated type", + AnchorFailure::Field => "struct field", + AnchorFailure::Method => "method", + AnchorFailure::MultipleAnchors => unreachable!("should be handled already"), + }; + + format!( + "`{}` contains an anchor, but links to {kind}s are already anchored", + path_str, + kind = kind + ) + } + }; + + report_diagnostic(cx, &msg, item, dox, link_range, |diag, sp| { + if let Some(sp) = sp { + diag.span_label(sp, "contains invalid anchor"); + } + }); } fn ambiguity_error( @@ -963,121 +976,100 @@ fn ambiguity_error( link_range: Option>, candidates: PerNS>, ) { - let hir_id = match cx.as_local_hir_id(item.def_id) { - Some(hir_id) => hir_id, - None => { - // If non-local, no need to check anything. - return; + let mut msg = format!("`{}` is ", path_str); + + let candidates = [TypeNS, ValueNS, MacroNS] + .iter() + .filter_map(|&ns| candidates[ns].map(|res| (res, ns))) + .collect::>(); + match candidates.as_slice() { + [(first_def, _), (second_def, _)] => { + msg += &format!( + "both {} {} and {} {}", + first_def.article(), + first_def.descr(), + second_def.article(), + second_def.descr(), + ); } - }; - let attrs = &item.attrs; - let sp = span_of_attrs(attrs).unwrap_or(item.source.span()); - - cx.tcx.struct_span_lint_hir( - lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - hir_id, - sp, - |lint| { - let mut msg = format!("`{}` is ", path_str); - - let candidates = [TypeNS, ValueNS, MacroNS] - .iter() - .filter_map(|&ns| candidates[ns].map(|res| (res, ns))) - .collect::>(); - match candidates.as_slice() { - [(first_def, _), (second_def, _)] => { - msg += &format!( - "both {} {} and {} {}", - first_def.article(), - first_def.descr(), - second_def.article(), - second_def.descr(), - ); - } - _ => { - let mut candidates = candidates.iter().peekable(); - while let Some((res, _)) = candidates.next() { - if candidates.peek().is_some() { - msg += &format!("{} {}, ", res.article(), res.descr()); - } else { - msg += &format!("and {} {}", res.article(), res.descr()); - } - } + _ => { + let mut candidates = candidates.iter().peekable(); + while let Some((res, _)) = candidates.next() { + if candidates.peek().is_some() { + msg += &format!("{} {}, ", res.article(), res.descr()); + } else { + msg += &format!("and {} {}", res.article(), res.descr()); } } + } + } - let mut diag = lint.build(&msg); + report_diagnostic(cx, &msg, item, dox, link_range.clone(), |diag, sp| { + if let Some(sp) = sp { + diag.span_label(sp, "ambiguous link"); - if let Some(link_range) = link_range { - if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) - { - diag.set_span(sp); - diag.span_label(sp, "ambiguous link"); + let link_range = link_range.expect("must have a link range if we have a span"); - for (res, ns) in candidates { - let (action, mut suggestion) = match res { - Res::Def(DefKind::AssocFn | DefKind::Fn, _) => { - ("add parentheses", format!("{}()", path_str)) - } - Res::Def(DefKind::Macro(MacroKind::Bang), _) => { - ("add an exclamation mark", format!("{}!", path_str)) - } - _ => { - let type_ = match (res, ns) { - (Res::Def(DefKind::Const, _), _) => "const", - (Res::Def(DefKind::Static, _), _) => "static", - (Res::Def(DefKind::Struct, _), _) => "struct", - (Res::Def(DefKind::Enum, _), _) => "enum", - (Res::Def(DefKind::Union, _), _) => "union", - (Res::Def(DefKind::Trait, _), _) => "trait", - (Res::Def(DefKind::Mod, _), _) => "module", - (_, TypeNS) => "type", - (_, ValueNS) => "value", - (Res::Def(DefKind::Macro(MacroKind::Derive), _), MacroNS) => { - "derive" - } - (_, MacroNS) => "macro", - }; - - // FIXME: if this is an implied shortcut link, it's bad style to suggest `@` - ("prefix with the item type", format!("{}@{}", type_, path_str)) - } + for (res, ns) in candidates { + let (action, mut suggestion) = match res { + Res::Def(DefKind::AssocFn | DefKind::Fn, _) => { + ("add parentheses", format!("{}()", path_str)) + } + Res::Def(DefKind::Macro(MacroKind::Bang), _) => { + ("add an exclamation mark", format!("{}!", path_str)) + } + _ => { + let type_ = match (res, ns) { + (Res::Def(DefKind::Const, _), _) => "const", + (Res::Def(DefKind::Static, _), _) => "static", + (Res::Def(DefKind::Struct, _), _) => "struct", + (Res::Def(DefKind::Enum, _), _) => "enum", + (Res::Def(DefKind::Union, _), _) => "union", + (Res::Def(DefKind::Trait, _), _) => "trait", + (Res::Def(DefKind::Mod, _), _) => "module", + (_, TypeNS) => "type", + (_, ValueNS) => "value", + (Res::Def(DefKind::Macro(MacroKind::Derive), _), MacroNS) => "derive", + (_, MacroNS) => "macro", }; - if dox.bytes().nth(link_range.start) == Some(b'`') { - suggestion = format!("`{}`", suggestion); - } - - diag.span_suggestion( - sp, - &format!("to link to the {}, {}", res.descr(), action), - suggestion, - Applicability::MaybeIncorrect, - ); + // FIXME: if this is an implied shortcut link, it's bad style to suggest `@` + ("prefix with the item type", format!("{}@{}", type_, path_str)) } - } else { - // blah blah blah\nblah\nblah [blah] blah blah\nblah blah - // ^ ~~~~ - // | link_range - // last_new_line_offset - let last_new_line_offset = - dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1); - let line = dox[last_new_line_offset..].lines().next().unwrap_or(""); + }; - // Print the line containing the `link_range` and manually mark it with '^'s. - diag.note(&format!( - "the link appears in this line:\n\n{line}\n\ - {indicator: , + item: &Item, + path_str: &str, + dox: &str, + link_range: Option>, +) { + let item_name = item.name.as_deref().unwrap_or(""); + let msg = + format!("public documentation for `{}` links to private item `{}`", item_name, path_str); + + report_diagnostic(cx, &msg, item, dox, link_range, |diag, sp| { + if let Some(sp) = sp { + diag.span_label(sp, "this item is private"); + } + }); } /// Given an enum variant's res, return the res of its enum and the associated fragment. @@ -1089,7 +1081,7 @@ fn handle_variant( use rustc_middle::ty::DefIdTree; if extra_fragment.is_some() { - return Err(ErrorKind::AnchorFailure("variants cannot be followed by anchors")); + return Err(ErrorKind::AnchorFailure(AnchorFailure::Variant)); } let parent = if let Some(parent) = cx.tcx.parent(res.def_id()) { parent diff --git a/src/test/codegen/abi-efiapi.rs b/src/test/codegen/abi-efiapi.rs index 8aeee5859d0ad..7c61b7809901f 100644 --- a/src/test/codegen/abi-efiapi.rs +++ b/src/test/codegen/abi-efiapi.rs @@ -2,7 +2,7 @@ // revisions:x86_64 i686 arm -// min-llvm-version 9.0 +// min-llvm-version: 9.0 //[x86_64] compile-flags: --target x86_64-unknown-uefi //[i686] compile-flags: --target i686-unknown-linux-musl diff --git a/src/test/codegen/cfguard-checks.rs b/src/test/codegen/cfguard-checks.rs index 96a0a321199a3..571a2654bcbfd 100644 --- a/src/test/codegen/cfguard-checks.rs +++ b/src/test/codegen/cfguard-checks.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control-flow-guard=checks +// compile-flags: -C control-flow-guard=checks // only-msvc #![crate_type = "lib"] diff --git a/src/test/codegen/cfguard-disabled.rs b/src/test/codegen/cfguard-disabled.rs index 925e4e8e2d155..c3f8f4116819c 100644 --- a/src/test/codegen/cfguard-disabled.rs +++ b/src/test/codegen/cfguard-disabled.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control-flow-guard=no +// compile-flags: -C control-flow-guard=no // only-msvc #![crate_type = "lib"] diff --git a/src/test/codegen/cfguard-nochecks.rs b/src/test/codegen/cfguard-nochecks.rs index d7dc3d7e89eea..3847c3e81ed7a 100644 --- a/src/test/codegen/cfguard-nochecks.rs +++ b/src/test/codegen/cfguard-nochecks.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control-flow-guard=nochecks +// compile-flags: -C control-flow-guard=nochecks // only-msvc #![crate_type = "lib"] diff --git a/src/test/codegen/cfguard-non-msvc.rs b/src/test/codegen/cfguard-non-msvc.rs index 4008f0187a0b0..6278a951e35f1 100644 --- a/src/test/codegen/cfguard-non-msvc.rs +++ b/src/test/codegen/cfguard-non-msvc.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control-flow-guard +// compile-flags: -C control-flow-guard // ignore-msvc #![crate_type = "lib"] diff --git a/src/test/codegen/force-unwind-tables.rs b/src/test/codegen/force-unwind-tables.rs index fbaf38d69df7f..eba4a7469f930 100644 --- a/src/test/codegen/force-unwind-tables.rs +++ b/src/test/codegen/force-unwind-tables.rs @@ -1,4 +1,4 @@ -// min-llvm-version 8.0 +// min-llvm-version: 8.0 // compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y #![crate_type="lib"] diff --git a/src/test/debuginfo/function-call.rs b/src/test/debuginfo/function-call.rs index 98ad8983a60a0..a5d5942b53953 100644 --- a/src/test/debuginfo/function-call.rs +++ b/src/test/debuginfo/function-call.rs @@ -1,5 +1,5 @@ // This test does not passed with gdb < 8.0. See #53497. -// min-gdb-version 8.0 +// min-gdb-version: 8.0 // compile-flags:-g diff --git a/src/test/debuginfo/pretty-huge-vec.rs b/src/test/debuginfo/pretty-huge-vec.rs index 2616c9465246e..cbd2278f7e27c 100644 --- a/src/test/debuginfo/pretty-huge-vec.rs +++ b/src/test/debuginfo/pretty-huge-vec.rs @@ -2,7 +2,7 @@ // ignore-freebsd: gdb package too new // ignore-android: FIXME(#10381) // compile-flags:-g -// min-gdb-version 8.1 +// min-gdb-version: 8.1 // min-lldb-version: 310 // === GDB TESTS =================================================================================== diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs index 4e95a028e0749..a4fbff5725c97 100644 --- a/src/test/debuginfo/pretty-std-collections.rs +++ b/src/test/debuginfo/pretty-std-collections.rs @@ -6,7 +6,7 @@ // The pretty printers being tested here require the patch from // https://sourceware.org/bugzilla/show_bug.cgi?id=21763 -// min-gdb-version 8.1 +// min-gdb-version: 8.1 // min-lldb-version: 310 diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 57721ce103c39..7ae82d522b09d 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -2,7 +2,7 @@ // only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 // ignore-android: FIXME(#10381) // compile-flags:-g -// min-gdb-version 7.7 +// min-gdb-version: 7.7 // min-lldb-version: 310 // === GDB TESTS =================================================================================== diff --git a/src/test/debuginfo/pretty-uninitialized-vec.rs b/src/test/debuginfo/pretty-uninitialized-vec.rs index 7ce004681e100..61791f48f4db7 100644 --- a/src/test/debuginfo/pretty-uninitialized-vec.rs +++ b/src/test/debuginfo/pretty-uninitialized-vec.rs @@ -2,7 +2,7 @@ // ignore-freebsd: gdb package too new // ignore-android: FIXME(#10381) // compile-flags:-g -// min-gdb-version 8.1 +// min-gdb-version: 8.1 // min-lldb-version: 310 // === GDB TESTS =================================================================================== diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs index a0a5b141ec0e1..5830ef033d389 100644 --- a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs @@ -91,3 +91,58 @@ pub unsafe extern "C" fn check_varargs_1(_: c_int, mut ap: ...) -> usize { pub unsafe extern "C" fn check_varargs_2(_: c_int, _ap: ...) -> usize { 0 } + +#[no_mangle] +pub unsafe extern "C" fn check_varargs_3(_: c_int, mut ap: ...) -> usize { + continue_if!(ap.arg::() == 1); + continue_if!(ap.arg::() == 2); + continue_if!(ap.arg::() == 3); + continue_if!(ap.arg::() == 4); + continue_if!(ap.arg::() == 5); + continue_if!(ap.arg::() == 6); + continue_if!(ap.arg::() == 7); + continue_if!(ap.arg::() == 8); + continue_if!(ap.arg::() == 9); + continue_if!(ap.arg::() == 10); + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_varargs_4(_: c_double, mut ap: ...) -> usize { + continue_if!(ap.arg::() == 1.0); + continue_if!(ap.arg::() == 2.0); + continue_if!(ap.arg::() == 3.0); + continue_if!(ap.arg::() == 4.0); + continue_if!(ap.arg::() == 5.0); + continue_if!(ap.arg::() == 6.0); + continue_if!(ap.arg::() == 7.0); + continue_if!(ap.arg::() == 8.0); + continue_if!(ap.arg::() == 9.0); + continue_if!(ap.arg::() == 10.0); + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn check_varargs_5(_: c_int, mut ap: ...) -> usize { + continue_if!(ap.arg::() == 1.0); + continue_if!(ap.arg::() == 1); + continue_if!(ap.arg::() == 2.0); + continue_if!(ap.arg::() == 2); + continue_if!(ap.arg::() == 3.0); + continue_if!(ap.arg::() == 3); + continue_if!(ap.arg::() == 4.0); + continue_if!(ap.arg::() == 4); + continue_if!(ap.arg::() == 5); + continue_if!(ap.arg::() == 5.0); + continue_if!(ap.arg::() == 6); + continue_if!(ap.arg::() == 6.0); + continue_if!(ap.arg::() == 7); + continue_if!(ap.arg::() == 7.0); + continue_if!(ap.arg::() == 8); + continue_if!(ap.arg::() == 8.0); + continue_if!(ap.arg::() == 9); + continue_if!(ap.arg::() == 9.0); + continue_if!(ap.arg::() == 10); + continue_if!(ap.arg::() == 10.0); + 0 +} diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c index 91b060dce26f4..5bdb51680a656 100644 --- a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c @@ -11,6 +11,9 @@ extern size_t check_list_copy_0(va_list ap); extern size_t check_varargs_0(int fixed, ...); extern size_t check_varargs_1(int fixed, ...); extern size_t check_varargs_2(int fixed, ...); +extern size_t check_varargs_3(int fixed, ...); +extern size_t check_varargs_4(double fixed, ...); +extern size_t check_varargs_5(int fixed, ...); int test_rust(size_t (*fn)(va_list), ...) { size_t ret = 0; @@ -36,5 +39,12 @@ int main(int argc, char* argv[]) { assert(check_varargs_2(0, "All", "of", "these", "are", "ignored", ".") == 0); + assert(check_varargs_3(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) == 0); + + assert(check_varargs_4(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) == 0); + + assert(check_varargs_5(0, 1.0, 1, 2.0, 2, 3.0, 3, 4.0, 4, 5, 5.0, 6, 6.0, 7, 7.0, 8, 8.0, + 9, 9.0, 10, 10.0) == 0); + return 0; } diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr index bc21cfd47c5d1..894518faa3168 100644 --- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr +++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr @@ -1,15 +1,15 @@ -error: `[v2]` cannot be resolved, ignoring it. +error: unresolved link to `v2` --> $DIR/deny-intra-link-resolution-failure.rs:3:6 | LL | /// [v2] - | ^^ cannot be resolved, ignoring + | ^^ unresolved link | note: the lint level is defined here --> $DIR/deny-intra-link-resolution-failure.rs:1:9 | LL | #![deny(intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr index cf26675163054..d2b2b90a4e50d 100644 --- a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr +++ b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr @@ -1,15 +1,15 @@ -error: `[TypeAlias::hoge]` cannot be resolved, ignoring it. +error: unresolved link to `TypeAlias::hoge` --> $DIR/intra-doc-alias-ice.rs:5:30 | LL | /// [broken cross-reference](TypeAlias::hoge) - | ^^^^^^^^^^^^^^^ cannot be resolved, ignoring + | ^^^^^^^^^^^^^^^ unresolved link | note: the lint level is defined here --> $DIR/intra-doc-alias-ice.rs:1:9 | LL | #![deny(intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.rs b/src/test/rustdoc-ui/intra-link-span-ice-55723.rs index 44997c90f5932..95388003f8470 100644 --- a/src/test/rustdoc-ui/intra-link-span-ice-55723.rs +++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.rs @@ -7,7 +7,7 @@ /// ## For example: /// /// (arr[i]) -//~^ ERROR `[i]` cannot be resolved, ignoring it. +//~^ ERROR `i` pub fn test_ice() { unimplemented!(); } diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr index ce31eb3a8a378..156e214a79ff0 100644 --- a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr +++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr @@ -1,15 +1,15 @@ -error: `[i]` cannot be resolved, ignoring it. +error: unresolved link to `i` --> $DIR/intra-link-span-ice-55723.rs:9:10 | LL | /// (arr[i]) - | ^ cannot be resolved, ignoring + | ^ unresolved link | note: the lint level is defined here --> $DIR/intra-link-span-ice-55723.rs:1:9 | LL | #![deny(intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-links-anchors.rs b/src/test/rustdoc-ui/intra-links-anchors.rs index 7f8a8dd3c45e0..7e61bd725359a 100644 --- a/src/test/rustdoc-ui/intra-links-anchors.rs +++ b/src/test/rustdoc-ui/intra-links-anchors.rs @@ -23,23 +23,23 @@ pub enum Enum { /// Like [Foo#hola]. /// /// Or maybe [Foo::f#hola]. -//~^ ERROR `[Foo::f#hola]` has an issue with the link anchor. +//~^ ERROR `Foo::f#hola` contains an anchor pub fn foo() {} /// Empty. /// /// Another anchor error: [hello#people#!]. -//~^ ERROR `[hello#people#!]` has an issue with the link anchor. +//~^ ERROR `hello#people#!` contains multiple anchors pub fn bar() {} /// Empty? /// /// Damn enum's variants: [Enum::A#whatever]. -//~^ ERROR `[Enum::A#whatever]` has an issue with the link anchor. +//~^ ERROR `Enum::A#whatever` contains an anchor pub fn enum_link() {} /// Primitives? /// /// [u32#hello] -//~^ ERROR `[u32#hello]` has an issue with the link anchor. +//~^ ERROR `u32#hello` contains an anchor pub fn x() {} diff --git a/src/test/rustdoc-ui/intra-links-anchors.stderr b/src/test/rustdoc-ui/intra-links-anchors.stderr index 11dee5547db4f..ef33d8f3e06fe 100644 --- a/src/test/rustdoc-ui/intra-links-anchors.stderr +++ b/src/test/rustdoc-ui/intra-links-anchors.stderr @@ -1,8 +1,8 @@ -error: `[Foo::f#hola]` has an issue with the link anchor. +error: `Foo::f#hola` contains an anchor, but links to struct fields are already anchored --> $DIR/intra-links-anchors.rs:25:15 | LL | /// Or maybe [Foo::f#hola]. - | ^^^^^^^^^^^ struct fields cannot be followed by anchors + | ^^^^^^^^^^^ contains invalid anchor | note: the lint level is defined here --> $DIR/intra-links-anchors.rs:1:9 @@ -10,23 +10,23 @@ note: the lint level is defined here LL | #![deny(intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `[hello#people#!]` has an issue with the link anchor. +error: `hello#people#!` contains multiple anchors --> $DIR/intra-links-anchors.rs:31:28 | LL | /// Another anchor error: [hello#people#!]. - | ^^^^^^^^^^^^^^ only one `#` is allowed in a link + | ^^^^^^^^^^^^^^ contains invalid anchor -error: `[Enum::A#whatever]` has an issue with the link anchor. +error: `Enum::A#whatever` contains an anchor, but links to enum variants are already anchored --> $DIR/intra-links-anchors.rs:37:28 | LL | /// Damn enum's variants: [Enum::A#whatever]. - | ^^^^^^^^^^^^^^^^ variants cannot be followed by anchors + | ^^^^^^^^^^^^^^^^ contains invalid anchor -error: `[u32#hello]` has an issue with the link anchor. +error: `u32#hello` contains an anchor, but links to primitive types are already anchored --> $DIR/intra-links-anchors.rs:43:6 | LL | /// [u32#hello] - | ^^^^^^^^^ primitive types cannot be followed by anchors + | ^^^^^^^^^ contains invalid anchor error: aborting due to 4 previous errors diff --git a/src/test/rustdoc-ui/intra-links-private.public.stderr b/src/test/rustdoc-ui/intra-links-private.public.stderr index 0a8dafdaf9466..a124435b08a99 100644 --- a/src/test/rustdoc-ui/intra-links-private.public.stderr +++ b/src/test/rustdoc-ui/intra-links-private.public.stderr @@ -1,4 +1,4 @@ -warning: `[DontDocMe]` public documentation for `DocMe` links to a private item +warning: public documentation for `DocMe` links to private item `DontDocMe` --> $DIR/intra-links-private.rs:6:11 | LL | /// docs [DontDocMe] diff --git a/src/test/rustdoc-ui/intra-links-private.rs b/src/test/rustdoc-ui/intra-links-private.rs index 86cf9fed3dab4..1b97f6e61bd23 100644 --- a/src/test/rustdoc-ui/intra-links-private.rs +++ b/src/test/rustdoc-ui/intra-links-private.rs @@ -4,7 +4,7 @@ #![cfg_attr(private, deny(intra_doc_link_resolution_failure))] /// docs [DontDocMe] -//[public]~^ WARNING `[DontDocMe]` public documentation for `DocMe` links to a private item +//[public]~^ WARNING public documentation for `DocMe` links to private item `DontDocMe` // FIXME: for [private] we should also make sure the link was actually generated pub struct DocMe; struct DontDocMe; diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.rs b/src/test/rustdoc-ui/intra-links-warning-crlf.rs index 18c9837b0bb45..a19c33b53be09 100644 --- a/src/test/rustdoc-ui/intra-links-warning-crlf.rs +++ b/src/test/rustdoc-ui/intra-links-warning-crlf.rs @@ -6,16 +6,16 @@ /// [error] pub struct A; -//~^^ WARNING `[error]` cannot be resolved +//~^^ WARNING `error` /// /// docs [error1] -//~^ WARNING `[error1]` cannot be resolved +//~^ WARNING `error1` /// docs [error2] /// pub struct B; -//~^^^ WARNING `[error2]` cannot be resolved +//~^^^ WARNING `error2` /** * This is a multi-line comment. @@ -23,4 +23,4 @@ pub struct B; * It also has an [error]. */ pub struct C; -//~^^^ WARNING `[error]` cannot be resolved +//~^^^ WARNING `error` diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr index ac8691a8743ba..bc31264c170ea 100644 --- a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr +++ b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr @@ -1,35 +1,35 @@ -warning: `[error]` cannot be resolved, ignoring it. +warning: unresolved link to `error` --> $DIR/intra-links-warning-crlf.rs:7:6 | LL | /// [error] - | ^^^^^ cannot be resolved, ignoring + | ^^^^^ unresolved link | = note: `#[warn(intra_doc_link_resolution_failure)]` on by default - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error1]` cannot be resolved, ignoring it. +warning: unresolved link to `error1` --> $DIR/intra-links-warning-crlf.rs:12:11 | LL | /// docs [error1] - | ^^^^^^ cannot be resolved, ignoring + | ^^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error2]` cannot be resolved, ignoring it. +warning: unresolved link to `error2` --> $DIR/intra-links-warning-crlf.rs:15:11 | LL | /// docs [error2] - | ^^^^^^ cannot be resolved, ignoring + | ^^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error]` cannot be resolved, ignoring it. +warning: unresolved link to `error` --> $DIR/intra-links-warning-crlf.rs:23:20 | LL | * It also has an [error]. - | ^^^^^ cannot be resolved, ignoring + | ^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: 4 warnings emitted diff --git a/src/test/rustdoc-ui/intra-links-warning.rs b/src/test/rustdoc-ui/intra-links-warning.rs index 623dcc320bb8d..eab1f03480460 100644 --- a/src/test/rustdoc-ui/intra-links-warning.rs +++ b/src/test/rustdoc-ui/intra-links-warning.rs @@ -1,37 +1,37 @@ // check-pass //! Test with [Foo::baz], [Bar::foo], ... -//~^ WARNING `[Foo::baz]` cannot be resolved -//~| WARNING `[Bar::foo]` cannot be resolved +//~^ WARNING `Foo::baz` +//~| WARNING `Bar::foo` //! , [Uniooon::X] and [Qux::Z]. -//~^ WARNING `[Uniooon::X]` cannot be resolved -//~| WARNING `[Qux::Z]` cannot be resolved +//~^ WARNING `Uniooon::X` +//~| WARNING `Qux::Z` //! //! , [Uniooon::X] and [Qux::Z]. -//~^ WARNING `[Uniooon::X]` cannot be resolved -//~| WARNING `[Qux::Z]` cannot be resolved +//~^ WARNING `Uniooon::X` +//~| WARNING `Qux::Z` /// [Qux:Y] -//~^ WARNING `[Qux:Y]` cannot be resolved +//~^ WARNING `Qux:Y` pub struct Foo { pub bar: usize, } /// Foo -/// bar [BarA] bar //~ WARNING `[BarA]` cannot be resolved +/// bar [BarA] bar //~ WARNING `BarA` /// baz pub fn a() {} /** * Foo - * bar [BarB] bar //~ WARNING `[BarB]` cannot be resolved + * bar [BarB] bar //~ WARNING `BarB` * baz */ pub fn b() {} /** Foo -bar [BarC] bar //~ WARNING `[BarC]` cannot be resolved +bar [BarC] bar //~ WARNING `BarC` baz let bar_c_1 = 0; @@ -42,12 +42,12 @@ baz */ pub fn c() {} -#[doc = "Foo\nbar [BarD] bar\nbaz"] //~ WARNING `[BarD]` cannot be resolved +#[doc = "Foo\nbar [BarD] bar\nbaz"] //~ WARNING `BarD` pub fn d() {} macro_rules! f { ($f:expr) => { - #[doc = $f] //~ WARNING `[BarF]` cannot be resolved + #[doc = $f] //~ WARNING `BarF` pub fn f() {} } } @@ -55,30 +55,30 @@ f!("Foo\nbar [BarF] bar\nbaz"); /** # for example, * - * time to introduce a link [error]*/ //~ WARNING `[error]` cannot be resolved + * time to introduce a link [error]*/ //~ WARNING `error` pub struct A; /** * # for example, * - * time to introduce a link [error] //~ WARNING `[error]` cannot be resolved + * time to introduce a link [error] //~ WARNING `error` */ pub struct B; -#[doc = "single line [error]"] //~ WARNING `[error]` cannot be resolved +#[doc = "single line [error]"] //~ WARNING `error` pub struct C; -#[doc = "single line with \"escaping\" [error]"] //~ WARNING `[error]` cannot be resolved +#[doc = "single line with \"escaping\" [error]"] //~ WARNING `error` pub struct D; -/// Item docs. //~ WARNING `[error]` cannot be resolved +/// Item docs. //~ WARNING `error` #[doc="Hello there!"] /// [error] pub struct E; /// -/// docs [error1] //~ WARNING `[error1]` cannot be resolved +/// docs [error1] //~ WARNING `error1` -/// docs [error2] //~ WARNING `[error2]` cannot be resolved +/// docs [error2] //~ WARNING `error2` /// pub struct F; diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index 914a19fc536c7..81931399c240a 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -1,77 +1,77 @@ -warning: `[Foo::baz]` cannot be resolved, ignoring it. +warning: unresolved link to `Foo::baz` --> $DIR/intra-links-warning.rs:3:23 | LL | //! Test with [Foo::baz], [Bar::foo], ... - | ^^^^^^^^ cannot be resolved, ignoring + | ^^^^^^^^ unresolved link | = note: `#[warn(intra_doc_link_resolution_failure)]` on by default - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[Bar::foo]` cannot be resolved, ignoring it. +warning: unresolved link to `Bar::foo` --> $DIR/intra-links-warning.rs:3:35 | LL | //! Test with [Foo::baz], [Bar::foo], ... - | ^^^^^^^^ cannot be resolved, ignoring + | ^^^^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[Uniooon::X]` cannot be resolved, ignoring it. +warning: unresolved link to `Uniooon::X` --> $DIR/intra-links-warning.rs:6:13 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^^^^^ cannot be resolved, ignoring + | ^^^^^^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[Qux::Z]` cannot be resolved, ignoring it. +warning: unresolved link to `Qux::Z` --> $DIR/intra-links-warning.rs:6:30 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^ cannot be resolved, ignoring + | ^^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[Uniooon::X]` cannot be resolved, ignoring it. +warning: unresolved link to `Uniooon::X` --> $DIR/intra-links-warning.rs:10:14 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^^^^^ cannot be resolved, ignoring + | ^^^^^^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[Qux::Z]` cannot be resolved, ignoring it. +warning: unresolved link to `Qux::Z` --> $DIR/intra-links-warning.rs:10:31 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^ cannot be resolved, ignoring + | ^^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[Qux:Y]` cannot be resolved, ignoring it. +warning: unresolved link to `Qux:Y` --> $DIR/intra-links-warning.rs:14:13 | LL | /// [Qux:Y] - | ^^^^^ cannot be resolved, ignoring + | ^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error]` cannot be resolved, ignoring it. +warning: unresolved link to `error` --> $DIR/intra-links-warning.rs:58:30 | LL | * time to introduce a link [error]*/ - | ^^^^^ cannot be resolved, ignoring + | ^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error]` cannot be resolved, ignoring it. +warning: unresolved link to `error` --> $DIR/intra-links-warning.rs:64:30 | LL | * time to introduce a link [error] - | ^^^^^ cannot be resolved, ignoring + | ^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error]` cannot be resolved, ignoring it. +warning: unresolved link to `error` --> $DIR/intra-links-warning.rs:68:1 | LL | #[doc = "single line [error]"] @@ -81,9 +81,9 @@ LL | #[doc = "single line [error]"] single line [error] ^^^^^ - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error]` cannot be resolved, ignoring it. +warning: unresolved link to `error` --> $DIR/intra-links-warning.rs:71:1 | LL | #[doc = "single line with \"escaping\" [error]"] @@ -93,9 +93,9 @@ LL | #[doc = "single line with \"escaping\" [error]"] single line with "escaping" [error] ^^^^^ - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error]` cannot be resolved, ignoring it. +warning: unresolved link to `error` --> $DIR/intra-links-warning.rs:74:1 | LL | / /// Item docs. @@ -107,49 +107,49 @@ LL | | /// [error] [error] ^^^^^ - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error1]` cannot be resolved, ignoring it. +warning: unresolved link to `error1` --> $DIR/intra-links-warning.rs:80:11 | LL | /// docs [error1] - | ^^^^^^ cannot be resolved, ignoring + | ^^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[error2]` cannot be resolved, ignoring it. +warning: unresolved link to `error2` --> $DIR/intra-links-warning.rs:82:11 | LL | /// docs [error2] - | ^^^^^^ cannot be resolved, ignoring + | ^^^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[BarA]` cannot be resolved, ignoring it. +warning: unresolved link to `BarA` --> $DIR/intra-links-warning.rs:21:10 | LL | /// bar [BarA] bar - | ^^^^ cannot be resolved, ignoring + | ^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[BarB]` cannot be resolved, ignoring it. +warning: unresolved link to `BarB` --> $DIR/intra-links-warning.rs:27:9 | LL | * bar [BarB] bar - | ^^^^ cannot be resolved, ignoring + | ^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[BarC]` cannot be resolved, ignoring it. +warning: unresolved link to `BarC` --> $DIR/intra-links-warning.rs:34:6 | LL | bar [BarC] bar - | ^^^^ cannot be resolved, ignoring + | ^^^^ unresolved link | - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[BarD]` cannot be resolved, ignoring it. +warning: unresolved link to `BarD` --> $DIR/intra-links-warning.rs:45:1 | LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] @@ -159,9 +159,9 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] bar [BarD] bar ^^^^ - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: `[BarF]` cannot be resolved, ignoring it. +warning: unresolved link to `BarF` --> $DIR/intra-links-warning.rs:50:9 | LL | #[doc = $f] @@ -174,7 +174,7 @@ LL | f!("Foo\nbar [BarF] bar\nbaz"); bar [BarF] bar ^^^^ - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) warning: 19 warnings emitted diff --git a/src/test/rustdoc-ui/issue-74134.public.stderr b/src/test/rustdoc-ui/issue-74134.public.stderr index 03f95f19d326e..3c41f7e63e637 100644 --- a/src/test/rustdoc-ui/issue-74134.public.stderr +++ b/src/test/rustdoc-ui/issue-74134.public.stderr @@ -1,4 +1,4 @@ -warning: `[PrivateType]` public documentation for `public_item` links to a private item +warning: public documentation for `public_item` links to private item `PrivateType` --> $DIR/issue-74134.rs:19:10 | LL | /// [`PrivateType`] diff --git a/src/test/rustdoc-ui/issue-74134.rs b/src/test/rustdoc-ui/issue-74134.rs index d561c2dd89015..fe484b43fb6fc 100644 --- a/src/test/rustdoc-ui/issue-74134.rs +++ b/src/test/rustdoc-ui/issue-74134.rs @@ -17,7 +17,7 @@ pub struct PublicType; pub struct Public { /// [`PublicType`] /// [`PrivateType`] - //[public]~^ WARNING public documentation for `public_item` links to a private + //[public]~^ WARNING public documentation for `public_item` links to private item `PrivateType` pub public_item: u32, /// [`PublicType`] diff --git a/src/test/rustdoc-ui/lint-group.rs b/src/test/rustdoc-ui/lint-group.rs index 06766db5335a1..e58c8b12f68cb 100644 --- a/src/test/rustdoc-ui/lint-group.rs +++ b/src/test/rustdoc-ui/lint-group.rs @@ -11,7 +11,7 @@ /// ``` /// println!("sup"); /// ``` -pub fn link_error() {} //~^^^^^ ERROR cannot be resolved, ignoring it +pub fn link_error() {} //~^^^^^ ERROR unresolved link to `error` /// wait, this doesn't have a doctest? pub fn no_doctest() {} //~^ ERROR missing code example in this documentation diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr index 852c9120e0bf9..14d72e9aad3ba 100644 --- a/src/test/rustdoc-ui/lint-group.stderr +++ b/src/test/rustdoc-ui/lint-group.stderr @@ -15,11 +15,11 @@ LL | #![deny(rustdoc)] | ^^^^^^^ = note: `#[deny(private_doc_tests)]` implied by `#[deny(rustdoc)]` -error: `[error]` cannot be resolved, ignoring it. +error: unresolved link to `error` --> $DIR/lint-group.rs:9:29 | LL | /// what up, let's make an [error] - | ^^^^^ cannot be resolved, ignoring + | ^^^^^ unresolved link | note: the lint level is defined here --> $DIR/lint-group.rs:7:9 @@ -27,7 +27,7 @@ note: the lint level is defined here LL | #![deny(rustdoc)] | ^^^^^^^ = note: `#[deny(intra_doc_link_resolution_failure)]` implied by `#[deny(rustdoc)]` - = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: missing code example in this documentation --> $DIR/lint-group.rs:16:1 diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs index 8c6073e2f7a49..1eeb01ccc846e 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs @@ -35,7 +35,7 @@ fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { #[cfg(transmute)] // one instantiations: BAD fn baz<'a,'b>(x: &'a u32) -> &'static u32 { - bar(foo, x) //[transmute]~ ERROR E0495 + bar(foo, x) //[transmute]~ ERROR E0759 } #[cfg(krisskross)] // two instantiations, mixing and matching: BAD diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr index 5ea98dcd4a972..0be9b37263a48 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr @@ -1,26 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/project-fn-ret-contravariant.rs:38:8 | -LL | bar(foo, x) - | ^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8... - --> $DIR/project-fn-ret-contravariant.rs:37:8 - | LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 { - | ^^ -note: ...so that reference does not outlive borrowed content - --> $DIR/project-fn-ret-contravariant.rs:38:13 - | -LL | bar(foo, x) - | ^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that reference does not outlive borrowed content - --> $DIR/project-fn-ret-contravariant.rs:38:4 - | + | ------- this data with lifetime `'a`... LL | bar(foo, x) - | ^^^^^^^^^^^ + | ----^^^---- ...is captured and required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index 0034d796826de..08d864f7836d2 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -46,7 +46,7 @@ fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { // Cannot instantiate `foo` with any lifetime other than `'a`, // since it is provided as input. - bar(foo, x) //[transmute]~ ERROR E0495 + bar(foo, x) //[transmute]~ ERROR E0759 } #[cfg(krisskross)] // two instantiations, mixing and matching: BAD diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index ef57f9e0bc480..0a44864b24955 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,30 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/project-fn-ret-invariant.rs:49:9 | -LL | bar(foo, x) - | ^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 45:8... - --> $DIR/project-fn-ret-invariant.rs:45:8 - | LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { - | ^^ -note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:49:14 - | -LL | bar(foo, x) - | ^ - = note: expected `Type<'_>` - found `Type<'a>` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:49:5 - | + | -------- this data with lifetime `'a`... +... LL | bar(foo, x) - | ^^^^^^^^^^^ - = note: expected `Type<'static>` - found `Type<'_>` + | ----^^^---- ...is captured and required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/async-await/issues/issue-62097.rs b/src/test/ui/async-await/issues/issue-62097.rs index ea482d3667e2b..66ebbd83ffa9e 100644 --- a/src/test/ui/async-await/issues/issue-62097.rs +++ b/src/test/ui/async-await/issues/issue-62097.rs @@ -9,7 +9,7 @@ where struct Struct; impl Struct { - pub async fn run_dummy_fn(&self) { //~ ERROR cannot infer + pub async fn run_dummy_fn(&self) { //~ ERROR E0759 foo(|| self.bar()).await; } diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index 0f58b158904db..56a28d904b91d 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/issue-62097.rs:12:31 | LL | pub async fn run_dummy_fn(&self) { diff --git a/src/test/ui/cfguard-run.rs b/src/test/ui/cfguard-run.rs index 21368fad3b058..3c4f9a1f5ee2c 100644 --- a/src/test/ui/cfguard-run.rs +++ b/src/test/ui/cfguard-run.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z control-flow-guard +// compile-flags: -C control-flow-guard pub fn main() { println!("hello, world"); diff --git a/src/test/ui/consts/issue-73976-monomorphic.rs b/src/test/ui/consts/issue-73976-monomorphic.rs new file mode 100644 index 0000000000000..7706a97f23b48 --- /dev/null +++ b/src/test/ui/consts/issue-73976-monomorphic.rs @@ -0,0 +1,36 @@ +// check-pass +// +// This test is complement to the test in issue-73976-polymorphic.rs. +// In that test we ensure that polymorphic use of type_id and type_name in patterns +// will be properly rejected. This test will ensure that monomorphic use of these +// would not be wrongly rejected in patterns. + +#![feature(const_type_id)] +#![feature(const_type_name)] + +use std::any::{self, TypeId}; + +pub struct GetTypeId(T); + +impl GetTypeId { + pub const VALUE: TypeId = TypeId::of::(); +} + +const fn check_type_id() -> bool { + matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) +} + +pub struct GetTypeNameLen(T); + +impl GetTypeNameLen { + pub const VALUE: usize = any::type_name::().len(); +} + +const fn check_type_name_len() -> bool { + matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) +} + +fn main() { + assert!(check_type_id::()); + assert!(check_type_name_len::()); +} diff --git a/src/test/ui/consts/issue-73976-polymorphic.rs b/src/test/ui/consts/issue-73976-polymorphic.rs new file mode 100644 index 0000000000000..28b84518719a1 --- /dev/null +++ b/src/test/ui/consts/issue-73976-polymorphic.rs @@ -0,0 +1,40 @@ +// This test is from #73976. We previously did not check if a type is monomorphized +// before calculating its type id, which leads to the bizzare behaviour below that +// TypeId of a generic type does not match itself. +// +// This test case should either run-pass or be rejected at compile time. +// Currently we just disallow this usage and require pattern is monomorphic. + +#![feature(const_type_id)] +#![feature(const_type_name)] + +use std::any::{self, TypeId}; + +pub struct GetTypeId(T); + +impl GetTypeId { + pub const VALUE: TypeId = TypeId::of::(); +} + +const fn check_type_id() -> bool { + matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern +} + +pub struct GetTypeNameLen(T); + +impl GetTypeNameLen { + pub const VALUE: usize = any::type_name::().len(); +} + +const fn check_type_name_len() -> bool { + matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern +} + +fn main() { + assert!(check_type_id::()); + assert!(check_type_name_len::()); +} diff --git a/src/test/ui/consts/issue-73976-polymorphic.stderr b/src/test/ui/consts/issue-73976-polymorphic.stderr new file mode 100644 index 0000000000000..c90ce2bd06a67 --- /dev/null +++ b/src/test/ui/consts/issue-73976-polymorphic.stderr @@ -0,0 +1,26 @@ +error: could not evaluate constant pattern + --> $DIR/issue-73976-polymorphic.rs:20:37 + | +LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-73976-polymorphic.rs:32:42 + | +LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-73976-polymorphic.rs:20:37 + | +LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-73976-polymorphic.rs:32:42 + | +LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs b/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs index d4ad706d01bc2..89210fdf137e0 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs @@ -17,7 +17,7 @@ fn static_val(_: T) { } fn with_dyn_debug_static<'a>(x: Box) { - static_val(x); //~ ERROR cannot infer + static_val(x); //~ ERROR E0759 } fn not_static_val(_: T) { diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr index 268008c211129..b3bef677d19c1 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr @@ -1,30 +1,17 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/dyn-trait.rs:20:16 | -LL | static_val(x); - | ^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 19:26... - --> $DIR/dyn-trait.rs:19:26 - | LL | fn with_dyn_debug_static<'a>(x: Box) { - | ^^ -note: ...so that the expression is assignable - --> $DIR/dyn-trait.rs:20:16 - | + | ------------------- this data with lifetime `'a`... LL | static_val(x); - | ^ - = note: expected `std::boxed::Box` - found `std::boxed::Box<(dyn std::fmt::Debug + 'a)>` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the types are compatible + | ^ ...is captured here... + | +note: ...and is required to live as long as `'static` here --> $DIR/dyn-trait.rs:20:5 | LL | static_val(x); | ^^^^^^^^^^ - = note: expected `StaticTrait` - found `StaticTrait` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 3b339c5c3d7fc..4372de245078f 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -12,7 +12,7 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^^^^^^^^^^^ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:6:32 + --> $DIR/must_outlive_least_region_or_bound.rs:5:32 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | -- ^^^^^^^^^ opaque type requires that `'a` must outlive `'static` @@ -26,7 +26,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^^^^^^^^^^^ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:9:46 + --> $DIR/must_outlive_least_region_or_bound.rs:7:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | - ^ returning this value requires that `'1` must outlive `'static` @@ -36,7 +36,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } = help: consider replacing `'1` with `'static` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:12:55 + --> $DIR/must_outlive_least_region_or_bound.rs:9:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -45,7 +45,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } = help: consider replacing `'a` with `'static` error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/must_outlive_least_region_or_bound.rs:15:41 + --> $DIR/must_outlive_least_region_or_bound.rs:11:41 | LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | ---- ^ lifetime `'a` required @@ -53,7 +53,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:30:24 + --> $DIR/must_outlive_least_region_or_bound.rs:22:24 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` @@ -61,7 +61,7 @@ LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | let's call the lifetime of this reference `'1` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:37:69 + --> $DIR/must_outlive_least_region_or_bound.rs:28:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -70,7 +70,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } = help: consider replacing `'a` with `'static` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:42:61 + --> $DIR/must_outlive_least_region_or_bound.rs:32:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` @@ -80,7 +80,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 = help: consider adding the following bound: `'b: 'a` error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:47:51 + --> $DIR/must_outlive_least_region_or_bound.rs:37:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 9bf86fa66cded..51f488e45a6f3 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -1,41 +1,31 @@ use std::fmt::Debug; -fn elided(x: &i32) -> impl Copy { x } -//~^ ERROR cannot infer an appropriate lifetime +fn elided(x: &i32) -> impl Copy { x } //~ ERROR E0759 -fn explicit<'a>(x: &'a i32) -> impl Copy { x } -//~^ ERROR cannot infer an appropriate lifetime +fn explicit<'a>(x: &'a i32) -> impl Copy { x } //~ ERROR E0759 -fn elided2(x: &i32) -> impl Copy + 'static { x } -//~^ ERROR cannot infer an appropriate lifetime +fn elided2(x: &i32) -> impl Copy + 'static { x } //~ ERROR E0759 -fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } -//~^ ERROR cannot infer an appropriate lifetime +fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } //~ ERROR E0759 fn foo<'a>(x: &i32) -> impl Copy + 'a { x } //~^ ERROR explicit lifetime required in the type of `x` -fn elided3(x: &i32) -> Box { Box::new(x) } -//~^ ERROR cannot infer an appropriate lifetime +fn elided3(x: &i32) -> Box { Box::new(x) } //~ ERROR E0759 -fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } -//~^ ERROR cannot infer an appropriate lifetime +fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } //~ ERROR E0759 -fn elided4(x: &i32) -> Box { Box::new(x) } -//~^ ERROR cannot infer an appropriate lifetime +fn elided4(x: &i32) -> Box { Box::new(x) } //~ ERROR E0759 -fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } -//~^ ERROR cannot infer an appropriate lifetime +fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } //~ ERROR E0759 -fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } -//~^ ERROR cannot infer an appropriate lifetime -//~| ERROR cannot infer an appropriate lifetime +fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } //~ ERROR E0759 +//~^ ERROR E0759 trait LifetimeTrait<'a> {} impl<'a> LifetimeTrait<'a> for &'a i32 {} -fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } -//~^ ERROR cannot infer an appropriate lifetime +fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERROR E0759 // Tests that a closure type containing 'b cannot be returned from a type where // only 'a was expected. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index ffadcaae08e05..b040889217e47 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } @@ -16,8 +16,8 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:6:44 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:5:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ------- ^ ...is captured here... @@ -25,7 +25,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | this data with lifetime `'a`... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:6:32 + --> $DIR/must_outlive_least_region_or_bound.rs:5:32 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ^^^^^^^^^ @@ -34,8 +34,8 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:9:46 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:7:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ---- ^ ...is captured here... @@ -43,7 +43,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | this data with an anonymous lifetime `'_`... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:9:24 + --> $DIR/must_outlive_least_region_or_bound.rs:7:24 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ @@ -56,8 +56,8 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:12:55 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:9:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ------- ^ ...is captured here... @@ -65,7 +65,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | this data with lifetime `'a`... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:12:33 + --> $DIR/must_outlive_least_region_or_bound.rs:9:33 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ @@ -79,15 +79,15 @@ LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/must_outlive_least_region_or_bound.rs:15:24 + --> $DIR/must_outlive_least_region_or_bound.rs:11:24 | LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | ---- ^^^^^^^^^^^^^^ lifetime `'a` required | | | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:30:65 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:22:65 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static` @@ -101,14 +101,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:30:69 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:22:69 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:30:41 + --> $DIR/must_outlive_least_region_or_bound.rs:22:41 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | ^^^^^^^^^^ @@ -121,14 +121,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:37:69 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:28:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- this data with lifetime `'a`... ^ ...is captured here... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:37:34 + --> $DIR/must_outlive_least_region_or_bound.rs:28:34 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x | ^^^^^^^^^^^^ error[E0623]: lifetime mismatch - --> $DIR/must_outlive_least_region_or_bound.rs:42:61 + --> $DIR/must_outlive_least_region_or_bound.rs:32:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | ------- ^^^^^^^^^^^^^^^^ @@ -151,15 +151,15 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | this parameter and the return type are declared with different lifetimes... error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:47:51 + --> $DIR/must_outlive_least_region_or_bound.rs:37:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static +` -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:18:50 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:14:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ---- ^ ...is captured here, requiring it to live as long as `'static` @@ -171,8 +171,8 @@ help: to declare that the trait object captures data from argument `x`, you can LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:21:59 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:16:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ------- ^ ...is captured here, requiring it to live as long as `'static` @@ -184,8 +184,8 @@ help: to declare that the trait object captures data from argument `x`, you can LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:24:60 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:18:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ---- ^ ...is captured here, requiring it to live as long as `'static` @@ -201,8 +201,8 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:27:69 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:20:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static` diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index 123ea6af6b019..65178cc9d24c2 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -12,7 +12,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough - --> $DIR/static-return-lifetime-infered.rs:10:37 + --> $DIR/static-return-lifetime-infered.rs:9:37 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { | -- ^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs index 96f3652c226ea..518c52f5de4d7 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.rs +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs @@ -4,13 +4,11 @@ struct A { impl A { fn iter_values_anon(&self) -> impl Iterator { - self.x.iter().map(|a| a.0) + self.x.iter().map(|a| a.0) //~ ERROR E0759 } - //~^^ ERROR cannot infer an appropriate lifetime fn iter_values<'a>(&'a self) -> impl Iterator { - self.x.iter().map(|a| a.0) + self.x.iter().map(|a| a.0) //~ ERROR E0759 } - //~^^ ERROR cannot infer an appropriate lifetime } fn main() {} diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index df0db6e4fc6df..7c289b388223a 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { @@ -18,8 +18,8 @@ help: to declare that the `impl Trait` captures data from argument `self`, you c LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/static-return-lifetime-infered.rs:11:16 +error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/static-return-lifetime-infered.rs:10:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { | -------- this data with lifetime `'a`... @@ -29,7 +29,7 @@ LL | self.x.iter().map(|a| a.0) | ...is captured here... | note: ...and is required to live as long as `'static` here - --> $DIR/static-return-lifetime-infered.rs:10:37 + --> $DIR/static-return-lifetime-infered.rs:9:37 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-16922.rs b/src/test/ui/issues/issue-16922.rs index 827163ef83cf7..f048ccd2427cb 100644 --- a/src/test/ui/issues/issue-16922.rs +++ b/src/test/ui/issues/issue-16922.rs @@ -1,8 +1,7 @@ use std::any::Any; fn foo(value: &T) -> Box { - Box::new(value) as Box - //~^ ERROR cannot infer an appropriate lifetime + Box::new(value) as Box //~ ERROR E0759 } fn main() { diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 919594fc9af4b..6decc751321f9 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `value` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr index 8421dc1d0c130..1931934a2112a 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr @@ -1,28 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0759]: `fn` parameter has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/constant-in-expr-inherent-1.rs:8:5 | -LL | >::C - | ^^^^^^^^^^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 7:8... - --> $DIR/constant-in-expr-inherent-1.rs:7:8 - | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { - | ^^ -note: ...so that the types are compatible - --> $DIR/constant-in-expr-inherent-1.rs:8:5 - | -LL | >::C - | ^^^^^^^^^^^^ - = note: expected `Foo<'_>` - found `Foo<'a>` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that reference does not outlive borrowed content - --> $DIR/constant-in-expr-inherent-1.rs:8:5 - | + | ------- this data with lifetime `'a`... LL | >::C - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs index 708ab1cf38297..4a2665d8e1694 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs @@ -15,7 +15,7 @@ fn load(ss: &mut SomeStruct) -> Box { // `Box` defaults to a `'static` bound, so this return // is illegal. - ss.r //~ ERROR cannot infer an appropriate lifetime + ss.r //~ ERROR E0759 } fn store(ss: &mut SomeStruct, b: Box) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 1b1e0d9610724..70b99ef7869ca 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `ss` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs index 5d199149c39b8..9d3f485e31438 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs @@ -5,18 +5,18 @@ trait Foo {} impl<'a> Foo for &'a [u8] {} fn a(v: &[u8]) -> Box { - let x: Box = Box::new(v); //~ ERROR cannot infer an appropriate lifetime + let x: Box = Box::new(v); //~ ERROR E0759 x } fn b(v: &[u8]) -> Box { - Box::new(v) //~ ERROR cannot infer an appropriate lifetime + Box::new(v) //~ ERROR E0759 } fn c(v: &[u8]) -> Box { // same as previous case due to RFC 599 - Box::new(v) //~ ERROR cannot infer an appropriate lifetime + Box::new(v) //~ ERROR E0759 } fn d<'a,'b>(v: &'a [u8]) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 7f5a3a47976c7..63fea1f41626d 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { @@ -15,7 +15,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn a(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { @@ -32,7 +32,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn b(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { diff --git a/src/test/ui/regions/regions-addr-of-self.rs b/src/test/ui/regions/regions-addr-of-self.rs index 647212407fc8a..4eb1b275f163e 100644 --- a/src/test/ui/regions/regions-addr-of-self.rs +++ b/src/test/ui/regions/regions-addr-of-self.rs @@ -4,7 +4,7 @@ struct Dog { impl Dog { pub fn chase_cat(&mut self) { - let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer + let p: &'static mut usize = &mut self.cats_chased; //~ ERROR E0759 *p += 1; } diff --git a/src/test/ui/regions/regions-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr index a0b8b6b51e5a1..738691fd695eb 100644 --- a/src/test/ui/regions/regions-addr-of-self.stderr +++ b/src/test/ui/regions/regions-addr-of-self.stderr @@ -1,29 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/regions-addr-of-self.rs:7:37 | +LL | pub fn chase_cat(&mut self) { + | --------- this data with an anonymous lifetime `'_`... LL | let p: &'static mut usize = &mut self.cats_chased; - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5... - --> $DIR/regions-addr-of-self.rs:6:5 - | -LL | / pub fn chase_cat(&mut self) { -LL | | let p: &'static mut usize = &mut self.cats_chased; -LL | | *p += 1; -LL | | } - | |_____^ -note: ...so that reference does not outlive borrowed content - --> $DIR/regions-addr-of-self.rs:7:37 - | -LL | let p: &'static mut usize = &mut self.cats_chased; - | ^^^^^^^^^^^^^^^^^^^^^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that reference does not outlive borrowed content - --> $DIR/regions-addr-of-self.rs:7:37 - | -LL | let p: &'static mut usize = &mut self.cats_chased; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/regions/regions-close-object-into-object-2.rs b/src/test/ui/regions/regions-close-object-into-object-2.rs index 2364ba2728600..7144ab5a24c51 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.rs +++ b/src/test/ui/regions/regions-close-object-into-object-2.rs @@ -7,7 +7,7 @@ trait X { } impl<'a, T> X for B<'a, T> {} fn g<'a, T: 'static>(v: Box + 'a>) -> Box { - box B(&*v) as Box //~ ERROR cannot infer + box B(&*v) as Box //~ ERROR E0759 } fn main() { } diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 114e4052aae09..aab7ce993aa3c 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/regions-close-object-into-object-2.rs:10:11 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-4.rs b/src/test/ui/regions/regions-close-object-into-object-4.rs index d531077043686..4c087f264f92b 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.rs +++ b/src/test/ui/regions/regions-close-object-into-object-4.rs @@ -7,7 +7,7 @@ trait X { } impl<'a, T> X for B<'a, T> {} fn i<'a, T, U>(v: Box+'a>) -> Box { - box B(&*v) as Box //~ ERROR cannot infer + box B(&*v) as Box //~ ERROR E0759 } fn main() {} diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 850d81940791f..90f807a41c562 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/regions-close-object-into-object-4.rs:10:11 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs index 8617c0e9da8f7..55d964ac53405 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.rs +++ b/src/test/ui/regions/regions-proc-bound-capture.rs @@ -6,7 +6,7 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box(isize) + 'a> { fn static_proc(x: &isize) -> Box (isize) + 'static> { // This is illegal, because the region bound on `proc` is 'static. - Box::new(move || { *x }) //~ ERROR cannot infer an appropriate lifetime + Box::new(move || { *x }) //~ ERROR E0759 } fn main() { } diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index 67eee3bb6e281..e76073f4f6b13 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/regions-proc-bound-capture.rs:9:14 | LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs index 64d6ccf340916..9439df266d59b 100644 --- a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs +++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs @@ -2,7 +2,7 @@ // being run when compiling with new LLVM pass manager and ThinLTO. // Note: The issue occurred only on non-zero opt-level. // -// min-llvm-version 9.0 +// min-llvm-version: 9.0 // needs-sanitizer-support // needs-sanitizer-address // diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs index 0afe631f1e3fc..43998ca8c5784 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs @@ -6,7 +6,7 @@ struct Foo; impl Foo { async fn f(self: Pin<&Self>) -> impl Clone { self } - //~^ ERROR cannot infer an appropriate lifetime + //~^ ERROR E0759 } fn main() { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index f2fbb0ba7d755..9cd0fd328ffa0 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs index 5054568b18970..04935fc52ab9e 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs @@ -3,7 +3,7 @@ use std::pin::Pin; struct Foo; impl Foo { - fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR cannot infer an appropriate lifetime + fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR E0759 } fn main() { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 2e10ab3d3f9b8..cb9d5b56dbc5c 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr new file mode 100644 index 0000000000000..6921926590a69 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr @@ -0,0 +1,37 @@ +error[E0597]: `val` does not live long enough + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:22:9 + | +LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> { + | -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a` +LL | val.use_self() + | ^^^ borrowed value does not live long enough +LL | } + | - `val` dropped here while still borrowed + | +help: you can add a bound to the opaque type to make it last less than `'static` and match `'a` + | +LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> + 'a { + | ^^^^ + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:44:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:110:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0515, E0597. +For more information about an error, try `rustc --explain E0515`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs new file mode 100644 index 0000000000000..b2dc16a27e310 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -0,0 +1,113 @@ +// FIXME: the following cases need to suggest more things to make users reach a working end state. + +mod bav { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> { + val.use_self() //~ ERROR E0597 + } +} + +mod bap { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR E0515 + } +} + +// This case in particular requires the user to write all of the bounds we have in `mod bax`. +mod bay { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box + 'a>) -> &'a () { + val.use_self() //~ ERROR E0772 + } +} + +mod bax { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait<'a> { + fn use_self(&'a self) -> &'a () { panic!() } + } + trait Bar {} + + impl<'a> MyTrait<'a> for Box + 'a> { + fn use_self(&'a self) -> &'a () { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box + 'a>) -> &'a () { + val.use_self() + } +} + +mod baw { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl<'a> MyTrait for Box>> { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: Box>>) -> impl OtherTrait<'a> + 'a{ + val.use_self() //~ ERROR E0515 + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr new file mode 100644 index 0000000000000..00971b41c7ce6 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -0,0 +1,57 @@ +error[E0597]: `val` does not live long enough + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9 + | +LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> { + | -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a` +LL | val.use_self() + | ^^^ borrowed value does not live long enough +LL | } + | - `val` dropped here while still borrowed + | +help: you can add a bound to the opaque type to make it last less than `'static` and match `'a` + | +LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> + 'a { + | ^^^^ + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:13 + | +LL | fn use_it<'a>(val: Box + 'a>) -> &'a () { + | -------------------------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30 + | +LL | impl MyTrait for Box> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for Box + '_> { + | ^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0515, E0597. +For more information about an error, try `rustc --explain E0515`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed new file mode 100644 index 0000000000000..3c10f85d9423a --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed @@ -0,0 +1,112 @@ +// run-rustfix +#![allow(dead_code)] + +mod foo { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self::() //~ ERROR E0759 + } +} + +mod bar { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + val.use_self() //~ ERROR E0772 + } +} + +mod baz { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for Box { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for Box {} + + fn use_it<'a>(val: &'a Box) -> &'a () { + val.use_self() //~ ERROR E0772 + } +} + +mod bat { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + + impl dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR E0772 + } +} + +mod ban { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait + '_ {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR E0759 + } +} + +mod bal { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait + '_ {} + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + MyTrait::use_self(val) //~ ERROR E0759 + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr new file mode 100644 index 0000000000000..697467dc3a630 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr @@ -0,0 +1,42 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9 + | +LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | --- `val` is a reference that is only valid in the function body +LL | val.use_self::() + | ^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here + | + = help: consider replacing `'a` with `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | --- `val` is a reference that is only valid in the function body +LL | val.use_self() + | ^^^^^^^^^^^^^^ `val` escapes the function body here + | + = help: consider replacing `'a` with `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + | --- `val` is a reference that is only valid in the function body +LL | val.use_self() + | ^^^^^^^^^^^^^^ `val` escapes the function body here + | + = help: consider replacing `'a` with `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | --- `val` is a reference that is only valid in the function body +LL | MyTrait::use_self(val) + | ^^^^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here + | + = help: consider replacing `'a` with `'static` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs new file mode 100644 index 0000000000000..88ab03dfc1ef1 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -0,0 +1,112 @@ +// run-rustfix +#![allow(dead_code)] + +mod foo { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self::() //~ ERROR E0759 + } +} + +mod bar { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + val.use_self() //~ ERROR E0772 + } +} + +mod baz { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for Box { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for Box {} + + fn use_it<'a>(val: &'a Box) -> &'a () { + val.use_self() //~ ERROR E0772 + } +} + +mod bat { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + + impl dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR E0772 + } +} + +mod ban { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + val.use_self() //~ ERROR E0759 + } +} + +mod bal { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + MyTrait::use_self(val) //~ ERROR E0759 + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr new file mode 100644 index 0000000000000..2fb6c25fd1702 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -0,0 +1,134 @@ +error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13 + | +LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ---------------------- this data with lifetime `'a`... +LL | val.use_self::() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ^^^^ + +error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14 + | +LL | impl dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl dyn ObjectTrait + '_ { + | ^^^^ + +error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:13 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + | ------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:85:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^ +help: to declare that the `impl Trait` captures data from argument `val`, you can add an explicit `'a` lifetime bound + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ^^^^ + +error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:27 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ------------------- this data with lifetime `'a`... +LL | MyTrait::use_self(val) + | ^^^ ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9 + | +LL | MyTrait::use_self(val) + | ^^^^^^^^^^^^^^^^^ +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:104:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^ + +error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + | ------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ^^^^ + +error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13 + | +LL | fn use_it<'a>(val: &'a Box) -> &'a () { + | ----------------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30 + | +LL | impl MyTrait for Box { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for Box { + | ^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs index d3853445dfdfe..94dd826a15cae 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -16,7 +16,7 @@ fn foo(g: G, dest: &mut T) -> impl FnOnce() where G: Get { - move || { //~ ERROR cannot infer an appropriate lifetime + move || { //~ ERROR `dest` *dest = g.get(); } } diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 9ab060328537b..d7051515f1102 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -6,7 +6,7 @@ LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `dest` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs index f78edb1c83a4c..d8446e58dbb63 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs @@ -27,7 +27,7 @@ impl Bar { fn iter(&self) -> impl Iterator> { Iter { current: None, - remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + remaining: self.0.iter(), //~ ERROR E0759 } } } @@ -38,7 +38,7 @@ impl Baz { fn iter(&self) -> impl Iterator> + '_ { Iter { current: None, - remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + remaining: self.0.iter(), //~ ERROR E0759 } } } @@ -49,7 +49,7 @@ impl Bat { fn iter<'a>(&'a self) -> impl Iterator> + 'a { Iter { current: None, - remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + remaining: self.0.iter(), //~ ERROR E0759 } } } @@ -60,7 +60,7 @@ impl Ban { fn iter<'a>(&'a self) -> impl Iterator> { Iter { current: None, - remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + remaining: self.0.iter(), //~ ERROR E0759 } } } diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr index 1257e9b172cf7..9f30787f07cc6 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/trait-object-nested-in-impl-trait.rs:30:31 | LL | fn iter(&self) -> impl Iterator> { @@ -23,7 +23,7 @@ help: to declare that the trait object captures data from argument `self`, you c LL | fn iter(&self) -> impl Iterator> { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/trait-object-nested-in-impl-trait.rs:41:31 | LL | fn iter(&self) -> impl Iterator> + '_ { @@ -44,7 +44,7 @@ help: to declare that the trait object captures data from argument `self`, you c LL | fn iter(&self) -> impl Iterator> + '_ { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/trait-object-nested-in-impl-trait.rs:52:31 | LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { @@ -65,7 +65,7 @@ help: to declare that the trait object captures data from argument `self`, you c LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/trait-object-nested-in-impl-trait.rs:63:31 | LL | fn iter<'a>(&'a self) -> impl Iterator> { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs index d5aa18eb0f4e7..e951adf030f5c 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs @@ -5,7 +5,7 @@ fn a(items: &[T]) -> Box> { // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` - Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime + Box::new(items.iter()) //~ ERROR E0759 } fn b(items: &[T]) -> Box + '_> { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index dda5de431d309..dd804864dab4f 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `items` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/dyn-trait-underscore.rs:8:20 | LL | fn a(items: &[T]) -> Box> { diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 5f7373be65946..9269a63b41aab 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -271,13 +271,13 @@ pub struct Config { pub gdb_native_rust: bool, /// Version of LLDB - pub lldb_version: Option, + pub lldb_version: Option, /// Whether LLDB has native rust support pub lldb_native_rust: bool, /// Version of LLVM - pub llvm_version: Option, + pub llvm_version: Option, /// Is LLVM a system LLVM pub system_llvm: bool, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index d6e28e93c9667..2ab764eb9207c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -132,72 +132,46 @@ impl EarlyProps { fn ignore_gdb(config: &Config, line: &str) -> bool { if let Some(actual_version) = config.gdb_version { - if line.starts_with("min-gdb-version") { - let (start_ver, end_ver) = extract_gdb_version_range(line); + if let Some(rest) = line.strip_prefix("min-gdb-version:").map(str::trim) { + let (start_ver, end_ver) = extract_version_range(rest, extract_gdb_version) + .unwrap_or_else(|| { + panic!("couldn't parse version range: {:?}", rest); + }); if start_ver != end_ver { panic!("Expected single GDB version") } // Ignore if actual version is smaller the minimum required // version - actual_version < start_ver - } else if line.starts_with("ignore-gdb-version") { - let (min_version, max_version) = extract_gdb_version_range(line); + return actual_version < start_ver; + } else if let Some(rest) = line.strip_prefix("ignore-gdb-version:").map(str::trim) { + let (min_version, max_version) = + extract_version_range(rest, extract_gdb_version).unwrap_or_else(|| { + panic!("couldn't parse version range: {:?}", rest); + }); if max_version < min_version { panic!("Malformed GDB version range: max < min") } - actual_version >= min_version && actual_version <= max_version - } else { - false - } - } else { - false - } - } - - // Takes a directive of the form "ignore-gdb-version [- ]", - // returns the numeric representation of and as - // tuple: ( as u32, as u32) - // If the part is omitted, the second component of the tuple - // is the same as . - fn extract_gdb_version_range(line: &str) -> (u32, u32) { - const ERROR_MESSAGE: &'static str = "Malformed GDB version directive"; - - let range_components = line - .split(&[' ', '-'][..]) - .filter(|word| !word.is_empty()) - .map(extract_gdb_version) - .skip_while(Option::is_none) - .take(3) // 3 or more = invalid, so take at most 3. - .collect::>>(); - - match range_components.len() { - 1 => { - let v = range_components[0].unwrap(); - (v, v) - } - 2 => { - let v_min = range_components[0].unwrap(); - let v_max = range_components[1].expect(ERROR_MESSAGE); - (v_min, v_max) + return actual_version >= min_version && actual_version <= max_version; } - _ => panic!(ERROR_MESSAGE), } + false } fn ignore_lldb(config: &Config, line: &str) -> bool { - if let Some(ref actual_version) = config.lldb_version { - if line.starts_with("min-lldb-version") { - let min_version = line - .trim_end() - .rsplit(' ') - .next() - .expect("Malformed lldb version directive"); + if let Some(actual_version) = config.lldb_version { + if let Some(min_version) = line.strip_prefix("min-lldb-version:").map(str::trim) { + let min_version = min_version.parse().unwrap_or_else(|e| { + panic!( + "Unexpected format of LLDB version string: {}\n{:?}", + min_version, e + ); + }); // Ignore if actual version is smaller the minimum required // version - lldb_version_to_int(actual_version) < lldb_version_to_int(min_version) + actual_version < min_version } else if line.starts_with("rust-lldb") && !config.lldb_native_rust { true } else { @@ -212,48 +186,31 @@ impl EarlyProps { if config.system_llvm && line.starts_with("no-system-llvm") { return true; } - if let Some(ref actual_version) = config.llvm_version { - let actual_version = version_to_int(actual_version); - if line.starts_with("min-llvm-version") { - let min_version = line - .trim_end() - .rsplit(' ') - .next() - .expect("Malformed llvm version directive"); + if let Some(actual_version) = config.llvm_version { + if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) { + let min_version = extract_llvm_version(rest).unwrap(); // Ignore if actual version is smaller the minimum required // version - actual_version < version_to_int(min_version) - } else if line.starts_with("min-system-llvm-version") { - let min_version = line - .trim_end() - .rsplit(' ') - .next() - .expect("Malformed llvm version directive"); + actual_version < min_version + } else if let Some(rest) = + line.strip_prefix("min-system-llvm-version:").map(str::trim) + { + let min_version = extract_llvm_version(rest).unwrap(); // Ignore if using system LLVM and actual version // is smaller the minimum required version - config.system_llvm && actual_version < version_to_int(min_version) - } else if line.starts_with("ignore-llvm-version") { - // Syntax is: "ignore-llvm-version [- ]" - let range_components = line - .split(' ') - .skip(1) // Skip the directive. - .map(|s| s.trim()) - .filter(|word| !word.is_empty() && word != &"-") - .take(3) // 3 or more = invalid, so take at most 3. - .collect::>(); - match range_components.len() { - 1 => actual_version == version_to_int(range_components[0]), - 2 => { - let v_min = version_to_int(range_components[0]); - let v_max = version_to_int(range_components[1]); - if v_max < v_min { - panic!("Malformed LLVM version range: max < min") - } - // Ignore if version lies inside of range. - actual_version >= v_min && actual_version <= v_max - } - _ => panic!("Malformed LLVM version directive"), + config.system_llvm && actual_version < min_version + } else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim) + { + // Syntax is: "ignore-llvm-version: [- ]" + let (v_min, v_max) = extract_version_range(rest, extract_llvm_version) + .unwrap_or_else(|| { + panic!("couldn't parse version range: {:?}", rest); + }); + if v_max < v_min { + panic!("Malformed LLVM version range: max < min") } + // Ignore if version lies inside of range. + actual_version >= v_min && actual_version <= v_max } else { false } @@ -261,20 +218,6 @@ impl EarlyProps { false } } - - fn version_to_int(version: &str) -> u32 { - let version_without_suffix = version.trim_end_matches("git").split('-').next().unwrap(); - let components: Vec = version_without_suffix - .split('.') - .map(|s| s.parse().expect("Malformed version component")) - .collect(); - match components.len() { - 1 => components[0] * 10000, - 2 => components[0] * 10000 + components[1] * 100, - 3 => components[0] * 10000 + components[1] * 100 + components[2], - _ => panic!("Malformed version"), - } - } } } @@ -944,12 +887,6 @@ impl Config { } } -pub fn lldb_version_to_int(version_string: &str) -> isize { - let error_string = - format!("Encountered LLDB version string with unexpected format: {}", version_string); - version_string.parse().expect(&error_string) -} - fn expand_variables(mut value: String, config: &Config) -> String { const CWD: &'static str = "{{cwd}}"; const SRC_BASE: &'static str = "{{src-base}}"; @@ -990,3 +927,49 @@ fn parse_normalization_string(line: &mut &str) -> Option { *line = &line[end + 1..]; Some(result) } + +pub fn extract_llvm_version(version: &str) -> Option { + let version_without_suffix = version.trim_end_matches("git").split('-').next().unwrap(); + let components: Vec = version_without_suffix + .split('.') + .map(|s| s.parse().expect("Malformed version component")) + .collect(); + let version = match *components { + [a] => a * 10_000, + [a, b] => a * 10_000 + b * 100, + [a, b, c] => a * 10_000 + b * 100 + c, + _ => panic!("Malformed version"), + }; + Some(version) +} + +// Takes a directive of the form " [- ]", +// returns the numeric representation of and as +// tuple: ( as u32, as u32) +// If the part is omitted, the second component of the tuple +// is the same as . +fn extract_version_range(line: &str, parse: F) -> Option<(u32, u32)> +where + F: Fn(&str) -> Option, +{ + let mut splits = line.splitn(2, "- ").map(str::trim); + let min = splits.next().unwrap(); + if min.ends_with('-') { + return None; + } + + let max = splits.next(); + + if min.is_empty() { + return None; + } + + let min = parse(min)?; + let max = match max { + Some(max) if max.is_empty() => return None, + Some(max) => parse(max)?, + _ => min, + }; + + Some((min, max)) +} diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 72af34d78260b..1f82b137ee6cf 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -119,17 +119,17 @@ fn no_system_llvm() { fn llvm_version() { let mut config = config(); - config.llvm_version = Some("8.1.2-rust".to_owned()); - assert!(parse_rs(&config, "// min-llvm-version 9.0").ignore); + config.llvm_version = Some(80102); + assert!(parse_rs(&config, "// min-llvm-version: 9.0").ignore); - config.llvm_version = Some("9.0.1-rust-1.43.0-dev".to_owned()); - assert!(parse_rs(&config, "// min-llvm-version 9.2").ignore); + config.llvm_version = Some(90001); + assert!(parse_rs(&config, "// min-llvm-version: 9.2").ignore); - config.llvm_version = Some("9.3.1-rust-1.43.0-dev".to_owned()); - assert!(!parse_rs(&config, "// min-llvm-version 9.2").ignore); + config.llvm_version = Some(90301); + assert!(!parse_rs(&config, "// min-llvm-version: 9.2").ignore); - config.llvm_version = Some("10.0.0-rust".to_owned()); - assert!(!parse_rs(&config, "// min-llvm-version 9.0").ignore); + config.llvm_version = Some(100000); + assert!(!parse_rs(&config, "// min-llvm-version: 9.0").ignore); } #[test] @@ -220,3 +220,18 @@ fn sanitizers() { assert!(parse_rs(&config, "// needs-sanitizer-memory").ignore); assert!(parse_rs(&config, "// needs-sanitizer-thread").ignore); } + +#[test] +fn test_extract_version_range() { + use super::{extract_llvm_version, extract_version_range}; + + assert_eq!(extract_version_range("1.2.3 - 4.5.6", extract_llvm_version), Some((10203, 40506))); + assert_eq!(extract_version_range("0 - 4.5.6", extract_llvm_version), Some((0, 40506))); + assert_eq!(extract_version_range("1.2.3 -", extract_llvm_version), None); + assert_eq!(extract_version_range("1.2.3 - ", extract_llvm_version), None); + assert_eq!(extract_version_range("- 4.5.6", extract_llvm_version), None); + assert_eq!(extract_version_range("-", extract_llvm_version), None); + assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None); + assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None); + assert_eq!(extract_version_range("0 -", extract_llvm_version), None); +} diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 07eba22c6eeb3..bf3510ea0894b 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -166,14 +166,20 @@ pub fn parse_config(args: Vec) -> Config { let cdb = analyze_cdb(matches.opt_str("cdb"), &target); let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); - let (lldb_version, lldb_native_rust) = extract_lldb_version(matches.opt_str("lldb-version")); - - let color = match matches.opt_str("color").as_ref().map(|x| &**x) { + let (lldb_version, lldb_native_rust) = matches + .opt_str("lldb-version") + .as_deref() + .and_then(extract_lldb_version) + .map(|(v, b)| (Some(v), b)) + .unwrap_or((None, false)); + let color = match matches.opt_str("color").as_deref() { Some("auto") | None => ColorConfig::AutoColor, Some("always") => ColorConfig::AlwaysColor, Some("never") => ColorConfig::NeverColor, Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x), }; + let llvm_version = + matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version); let src_base = opt_path(matches, "src-base"); let run_ignored = matches.opt_present("ignored"); @@ -215,7 +221,7 @@ pub fn parse_config(args: Vec) -> Config { gdb_native_rust, lldb_version, lldb_native_rust, - llvm_version: matches.opt_str("llvm-version"), + llvm_version, system_llvm: matches.opt_present("system-llvm"), android_cross_path, adb_path: opt_str2(matches.opt_str("adb-path")), @@ -254,7 +260,7 @@ pub fn log_config(config: &Config) { logv(c, format!("stage_id: {}", config.stage_id)); logv(c, format!("mode: {}", config.mode)); logv(c, format!("run_ignored: {}", config.run_ignored)); - logv(c, format!("filter: {}", opt_str(&config.filter.as_ref().map(|re| re.to_owned())))); + logv(c, format!("filter: {}", opt_str(&config.filter))); logv(c, format!("filter_exact: {}", config.filter_exact)); logv( c, @@ -403,17 +409,14 @@ fn configure_lldb(config: &Config) -> Option { return None; } - if let Some(lldb_version) = config.lldb_version.as_ref() { - if lldb_version == "350" { - println!( - "WARNING: The used version of LLDB ({}) has a \ - known issue that breaks debuginfo tests. See \ - issue #32520 for more information. Skipping all \ - LLDB-based tests!", - lldb_version - ); - return None; - } + if let Some(350) = config.lldb_version { + println!( + "WARNING: The used version of LLDB (350) has a \ + known issue that breaks debuginfo tests. See \ + issue #32520 for more information. Skipping all \ + LLDB-based tests!", + ); + return None; } // Some older versions of LLDB seem to have problems with multiple @@ -727,9 +730,7 @@ fn make_test_closure( let config = config.clone(); let testpaths = testpaths.clone(); let revision = revision.cloned(); - test::DynTestFn(Box::new(move || { - runtest::run(config, &testpaths, revision.as_ref().map(|s| s.as_str())) - })) + test::DynTestFn(Box::new(move || runtest::run(config, &testpaths, revision.as_deref()))) } /// Returns `true` if the given target is an Android target for the @@ -845,75 +846,40 @@ fn extract_gdb_version(full_version_line: &str) -> Option { // This particular form is documented in the GNU coding standards: // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion - // don't start parsing in the middle of a number - let mut prev_was_digit = false; - let mut in_parens = false; - for (pos, c) in full_version_line.char_indices() { - if in_parens { - if c == ')' { - in_parens = false; - } - continue; - } else if c == '(' { - in_parens = true; - continue; - } - - if prev_was_digit || !c.is_digit(10) { - prev_was_digit = c.is_digit(10); - continue; + let mut splits = full_version_line.rsplit(' '); + let version_string = splits.next().unwrap(); + + let mut splits = version_string.split('.'); + let major = splits.next().unwrap(); + let minor = splits.next().unwrap(); + let patch = splits.next(); + + let major: u32 = major.parse().unwrap(); + let (minor, patch): (u32, u32) = match minor.find(not_a_digit) { + None => { + let minor = minor.parse().unwrap(); + let patch: u32 = match patch { + Some(patch) => match patch.find(not_a_digit) { + None => patch.parse().unwrap(), + Some(idx) if idx > 3 => 0, + Some(idx) => patch[..idx].parse().unwrap(), + }, + None => 0, + }; + (minor, patch) } - - prev_was_digit = true; - - let line = &full_version_line[pos..]; - - let next_split = match line.find(|c: char| !c.is_digit(10)) { - Some(idx) => idx, - None => continue, // no minor version - }; - - if line.as_bytes()[next_split] != b'.' { - continue; // no minor version + // There is no patch version after minor-date (e.g. "4-2012"). + Some(idx) => { + let minor = minor[..idx].parse().unwrap(); + (minor, 0) } + }; - let major = &line[..next_split]; - let line = &line[next_split + 1..]; - - let (minor, patch) = match line.find(|c: char| !c.is_digit(10)) { - Some(idx) => { - if line.as_bytes()[idx] == b'.' { - let patch = &line[idx + 1..]; - - let patch_len = - patch.find(|c: char| !c.is_digit(10)).unwrap_or_else(|| patch.len()); - let patch = &patch[..patch_len]; - let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) }; - - (&line[..idx], patch) - } else { - (&line[..idx], None) - } - } - None => (line, None), - }; - - if minor.is_empty() { - continue; - } - - let major: u32 = major.parse().unwrap(); - let minor: u32 = minor.parse().unwrap(); - let patch: u32 = patch.unwrap_or("0").parse().unwrap(); - - return Some(((major * 1000) + minor) * 1000 + patch); - } - - None + Some(((major * 1000) + minor) * 1000 + patch) } /// Returns (LLDB version, LLDB is rust-enabled) -fn extract_lldb_version(full_version_line: Option) -> (Option, bool) { +fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> { // Extract the major LLDB version from the given version string. // LLDB version strings are different for Apple and non-Apple platforms. // The Apple variant looks like this: @@ -922,7 +888,7 @@ fn extract_lldb_version(full_version_line: Option) -> (Option, b // lldb-300.2.51 (new versions) // // We are only interested in the major version number, so this function - // will return `Some("179")` and `Some("300")` respectively. + // will return `Some(179)` and `Some(300)` respectively. // // Upstream versions look like: // lldb version 6.0.1 @@ -934,53 +900,24 @@ fn extract_lldb_version(full_version_line: Option) -> (Option, b // normally fine because the only non-Apple version we test is // rust-enabled. - if let Some(ref full_version_line) = full_version_line { - if !full_version_line.trim().is_empty() { - let full_version_line = full_version_line.trim(); - - for (pos, l) in full_version_line.char_indices() { - if l != 'l' && l != 'L' { - continue; - } - if pos + 5 >= full_version_line.len() { - continue; - } - let l = full_version_line[pos + 1..].chars().next().unwrap(); - if l != 'l' && l != 'L' { - continue; - } - let d = full_version_line[pos + 2..].chars().next().unwrap(); - if d != 'd' && d != 'D' { - continue; - } - let b = full_version_line[pos + 3..].chars().next().unwrap(); - if b != 'b' && b != 'B' { - continue; - } - let dash = full_version_line[pos + 4..].chars().next().unwrap(); - if dash != '-' { - continue; - } - - let vers = full_version_line[pos + 5..] - .chars() - .take_while(|c| c.is_digit(10)) - .collect::(); - if !vers.is_empty() { - return (Some(vers), full_version_line.contains("rust-enabled")); - } - } + let full_version_line = full_version_line.trim(); - if full_version_line.starts_with("lldb version ") { - let vers = full_version_line[13..] - .chars() - .take_while(|c| c.is_digit(10)) - .collect::(); - if !vers.is_empty() { - return (Some(vers + "00"), full_version_line.contains("rust-enabled")); - } - } + if let Some(apple_ver) = + full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-")) + { + if let Some(idx) = apple_ver.find(not_a_digit) { + let version: u32 = apple_ver[..idx].parse().unwrap(); + return Some((version, full_version_line.contains("rust-enabled"))); + } + } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") { + if let Some(idx) = lldb_ver.find(not_a_digit) { + let version: u32 = lldb_ver[..idx].parse().unwrap(); + return Some((version * 100, full_version_line.contains("rust-enabled"))); } } - (None, false) + None +} + +fn not_a_digit(c: char) -> bool { + !c.is_digit(10) } diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs index 31c151d29e916..ea9bc1c1a5b7f 100644 --- a/src/tools/compiletest/src/tests.rs +++ b/src/tools/compiletest/src/tests.rs @@ -1,8 +1,9 @@ +use super::header::extract_llvm_version; use super::*; #[test] fn test_extract_gdb_version() { - macro_rules! test { ($($expectation:tt: $input:tt,)*) => {{$( + macro_rules! test { ($($expectation:literal: $input:literal,)*) => {{$( assert_eq!(extract_gdb_version($input), Some($expectation)); )*}}} @@ -41,6 +42,17 @@ fn test_extract_gdb_version() { } } +#[test] +fn test_extract_lldb_version() { + // Apple variants + assert_eq!(extract_lldb_version("LLDB-179.5"), Some((179, false))); + assert_eq!(extract_lldb_version("lldb-300.2.51"), Some((300, false))); + + // Upstream versions + assert_eq!(extract_lldb_version("lldb version 6.0.1"), Some((600, false))); + assert_eq!(extract_lldb_version("lldb version 9.0.0"), Some((900, false))); +} + #[test] fn is_test_test() { assert_eq!(true, is_test(&OsString::from("a_test.rs"))); @@ -49,3 +61,11 @@ fn is_test_test() { assert_eq!(false, is_test(&OsString::from("#a_dog_gif"))); assert_eq!(false, is_test(&OsString::from("~a_temp_file"))); } + +#[test] +fn test_extract_llvm_version() { + assert_eq!(extract_llvm_version("8.1.2-rust"), Some(80102)); + assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Some(90001)); + assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Some(90301)); + assert_eq!(extract_llvm_version("10.0.0-rust"), Some(100000)); +} diff --git a/triagebot.toml b/triagebot.toml index 51a29553fdb3d..ce4ea895400ac 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -81,7 +81,7 @@ topic = "I-prioritize #{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* issue #{number} has been requested for prioritization. -# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#Unprioritized-I-prioritize) +# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#assign-priority-to-unprioritized-issues-with-i-prioritize-label) - Priority? - Regression? - Notify people/groups? @@ -96,7 +96,7 @@ topic = "I-nominated #{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* #{number} has been nominated for discussion in `T-compiler` meeting. -# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#I-nominated) +# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-i-nominated-issues) - Already discussed? - Worth the meeting time? - Add agenda entry: @@ -113,7 +113,7 @@ topic = "Backport #{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* PR #{number} has been requested for beta backport. -# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#StableBeta-nominations) +# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations) Prepare agenda entry: - Why nominated? - Author, assignee? @@ -127,7 +127,7 @@ topic = "Backport #{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* PR #{number} has been requested for stable backport. -# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#StableBeta-nominations) +# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations) Prepare agenda entry: - Why nominated? - Author, assignee? @@ -142,7 +142,7 @@ topic = "S-waiting-on-team #{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* PR #{number} is waiting on `T-compiler`. -# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#PR%E2%80%99s-waiting-on-team) +# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-prs-waiting-on-team) - Prepare agenda entry: - What is it waiting for? - Important details? @@ -156,7 +156,7 @@ topic = "P-critical #{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* issue #{number} has been assigned `P-critical`. -# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#P-critical-and-Unassigned-P-high-regressions) +# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-p-critical-and-unassigned-p-high-regressions) - Notify people/groups? - Assign if possible? - Add to agenda: @@ -172,7 +172,7 @@ topic = "P-high regression #{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* issue #{number} has been assigned `P-high` and is a regression. -# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#P-critical-and-Unassigned-P-high-regressions) +# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-p-critical-and-unassigned-p-high-regressions) Is issue assigned? If not: - Try to find an assignee? - Otherwise add to agenda: