diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e51d6fff78847..f5463bca3384c 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2482,20 +2482,39 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { if let LinkerFlavor::Gcc = flavor { match ld_impl { LdImpl::Lld => { - let tools_path = - sess.host_filesearch(PathKind::All).get_tools_search_paths(false); - let lld_path = tools_path - .into_iter() - .map(|p| p.join("gcc-ld")) - .find(|p| { - p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists() - }) - .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found")); - cmd.cmd().arg({ - let mut arg = OsString::from("-B"); - arg.push(lld_path); - arg - }); + if sess.target.lld_flavor == LldFlavor::Ld64 { + let tools_path = + sess.host_filesearch(PathKind::All).get_tools_search_paths(false); + let ld64_exe = tools_path + .into_iter() + .map(|p| p.join("gcc-ld")) + .map(|p| { + p.join(if sess.host.is_like_windows { "ld64.exe" } else { "ld64" }) + }) + .find(|p| p.exists()) + .unwrap_or_else(|| sess.fatal("rust-lld (as ld64) not found")); + cmd.cmd().arg({ + let mut arg = OsString::from("-fuse-ld="); + arg.push(ld64_exe); + arg + }); + } else { + let tools_path = + sess.host_filesearch(PathKind::All).get_tools_search_paths(false); + let lld_path = tools_path + .into_iter() + .map(|p| p.join("gcc-ld")) + .find(|p| { + p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }) + .exists() + }) + .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found")); + cmd.cmd().arg({ + let mut arg = OsString::from("-B"); + arg.push(lld_path); + arg + }); + } } } } else { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs b/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs index 012d67255d13b..6426098d843fe 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs @@ -256,6 +256,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { let constraint_sets: Vec<_> = unnormalized_input_output_tys .flat_map(|ty| { debug!("build: input_or_output={:?}", ty); + // We add implied bounds from both the unnormalized and normalized ty + // See issue #87748 + let constraints_implied_1 = self.add_implied_bounds(ty); let TypeOpOutput { output: ty, constraints: constraints1, .. } = self .param_env .and(type_op::normalize::Normalize::new(ty)) @@ -271,9 +274,21 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { canonicalized_query: None, } }); - let constraints2 = self.add_implied_bounds(ty); + // Note: we need this in examples like + // ``` + // trait Foo { + // type Bar; + // fn foo(&self) -> &Self::Bar; + // } + // impl Foo for () { + // type Bar = (); + // fn foo(&self) ->&() {} + // } + // ``` + // Both &Self::Bar and &() are WF + let constraints_implied_2 = self.add_implied_bounds(ty); normalized_inputs_and_output.push(ty); - constraints1.into_iter().chain(constraints2) + constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2) }) .collect(); diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 5d75f6ab39ce7..a21b784e11b1c 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -1,6 +1,6 @@ use std::env; -use crate::spec::{FramePointer, SplitDebuginfo, TargetOptions}; +use crate::spec::{FramePointer, LldFlavor, SplitDebuginfo, TargetOptions}; pub fn opts(os: &str) -> TargetOptions { // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 @@ -35,6 +35,7 @@ pub fn opts(os: &str) -> TargetOptions { abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, eh_frame_header: false, + lld_flavor: LldFlavor::Ld64, // The historical default for macOS targets is to run `dsymutil` which // generates a packed version of debuginfo split from the main file. diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index c384e0dcb2cae..d59291b8fd493 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -250,6 +250,8 @@ fn compare_predicate_entailment<'tcx>( // Compute placeholder form of impl and trait method tys. let tcx = infcx.tcx; + let mut wf_tys = vec![]; + let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, infer::HigherRankedType, @@ -260,10 +262,18 @@ fn compare_predicate_entailment<'tcx>( let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); debug!("compare_impl_method: impl_fty={:?}", impl_fty); + // First liberate late bound regions and subst placeholders let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); + // Next, add all inputs and output as well-formed tys. Importantly, + // we have to do this before normalization, since the normalized ty may + // not contain the input parameters. See issue #87748. + wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig); + // Also add the resulting inputs and output as well-formed. + // This probably isn't strictly necessary. + wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); @@ -388,7 +398,7 @@ fn compare_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id); - fcx.regionck_item(impl_m_hir_id, impl_m_span, trait_sig.inputs_and_output); + fcx.regionck_item(impl_m_hir_id, impl_m_span, &wf_tys); Ok(()) }) diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index a88b1c7af5a96..803c440bbc98b 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -364,7 +364,7 @@ fn typeck_with_fallback<'tcx>( let typeck_results = Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); - let fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { + let (fcx, wf_tys) = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); >::ty_of_fn( @@ -383,17 +383,25 @@ fn typeck_with_fallback<'tcx>( check_abi(tcx, id, span, fn_sig.abi()); + // When normalizing the function signature, we assume all types are + // well-formed. So, we don't need to worry about the obligations + // from normalization. We could just discard these, but to align with + // compare_method and elsewhere, we just add implied bounds for + // these types. + let mut wf_tys = vec![]; // Compute the fty from point of view of inside the fn. let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); + wf_tys.extend(fn_sig.inputs_and_output.iter()); let fn_sig = inh.normalize_associated_types_in( body.value.span, body_id.hir_id, param_env, fn_sig, ); + wf_tys.extend(fn_sig.inputs_and_output.iter()); let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0; - fcx + (fcx, wf_tys) } else { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); let expected_type = body_ty @@ -443,7 +451,7 @@ fn typeck_with_fallback<'tcx>( fcx.write_ty(id, expected_type); - fcx + (fcx, vec![]) }; let fallback_has_occurred = fcx.type_inference_fallback(); @@ -467,7 +475,7 @@ fn typeck_with_fallback<'tcx>( fcx.select_all_obligations_or_error(); if fn_sig.is_some() { - fcx.regionck_fn(id, body); + fcx.regionck_fn(id, body, span, &wf_tys); } else { fcx.regionck_expr(body); } diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index ca6828cfdf68d..290fa5fc36719 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -144,11 +144,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// rest of type check and because sometimes we need type /// inference to have completed before we can determine which /// constraints to add. - pub fn regionck_fn(&self, fn_id: hir::HirId, body: &'tcx hir::Body<'tcx>) { + pub(crate) fn regionck_fn( + &self, + fn_id: hir::HirId, + body: &'tcx hir::Body<'tcx>, + span: Span, + wf_tys: &[Ty<'tcx>], + ) { debug!("regionck_fn(id={})", fn_id); let subject = self.tcx.hir().body_owner_def_id(body.id()); let hir_id = body.value.hir_id; let mut rcx = RegionCtxt::new(self, hir_id, Subject(subject), self.param_env); + // We need to add the implied bounds from the function signature + rcx.outlives_environment.add_implied_bounds(self, wf_tys, fn_id, span); + rcx.outlives_environment.save_implied_bounds(fn_id); if !self.errors_reported_since_creation() { // regionck assumes typeck succeeded diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 2e01e99d36ec6..5ade3828b7265 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -911,6 +911,7 @@ fn check_where_clauses<'tcx, 'fcx>( } } +#[tracing::instrument(level = "debug", skip(fcx, span, hir_decl))] fn check_fn_or_method<'fcx, 'tcx>( fcx: &FnCtxt<'fcx, 'tcx>, span: Span, @@ -921,6 +922,11 @@ fn check_fn_or_method<'fcx, 'tcx>( ) { let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); + // Unnormalized types in signature are WF too + implied_bounds.extend(sig.inputs()); + // FIXME(#27579) return types should not be implied bounds + implied_bounds.push(sig.output()); + // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` // on the entire `FnSig`, since this would use the same `WellFormedLoc` @@ -970,9 +976,11 @@ fn check_fn_or_method<'fcx, 'tcx>( ObligationCauseCode::ReturnType, ); - // FIXME(#25759) return types should not be implied bounds + // FIXME(#27579) return types should not be implied bounds implied_bounds.push(sig.output()); + debug!(?implied_bounds); + check_where_clauses(fcx, span, def_id, Some((sig.output(), hir_decl.output.span()))); } @@ -1117,6 +1125,7 @@ const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut se `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one \ of the previous types except `Self`)"; +#[tracing::instrument(level = "debug", skip(fcx))] fn check_method_receiver<'fcx, 'tcx>( fcx: &FnCtxt<'fcx, 'tcx>, fn_sig: &hir::FnSig<'_>, diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 024370f8d3711..7c7db4ac55f80 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -14,7 +14,7 @@ use rustc_index::vec::Idx; use rustc_infer::infer::InferCtxt; use rustc_middle::hir::place::ProjectionKind; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::{self, adjustment, TyCtxt}; +use rustc_middle::ty::{self, adjustment, AdtKind, TyCtxt}; use rustc_target::abi::VariantIdx; use std::iter; @@ -265,7 +265,20 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let place_ty = place.place.ty(); if let ty::Adt(def, _) = place_ty.kind() { - if def.variants.len() > 1 { + // Note that if a non-exhaustive SingleVariant is defined in another crate, we need + // to assume that more cases will be added to the variant in the future. This mean + // that we should handle non-exhaustive SingleVariant the same way we would handle + // a MultiVariant. + // If the variant is not local it must be defined in another crate. + let is_non_exhaustive = match def.adt_kind() { + AdtKind::Struct | AdtKind::Union => { + def.non_enum_variant().is_field_list_non_exhaustive() + } + AdtKind::Enum => def.is_variant_list_non_exhaustive(), + }; + if def.variants.len() > 1 + || (!def.did.is_local() && is_non_exhaustive) + { needs_to_be_read = true; } } else { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index d25989954783a..2a6a05e8e509d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -1121,6 +1121,10 @@ impl Step for Assemble { &lld_install.join("bin").join(&src_exe), &gcc_ld_dir.join(exe("ld", target_compiler.host)), ); + builder.copy( + &lld_install.join("bin").join(&src_exe), + &gcc_ld_dir.join(exe("ld64", target_compiler.host)), + ); } // Similarly, copy `llvm-dwp` into libdir for Split DWARF. Only copy it when the LLVM diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index d7d511c1c921b..7c1bb1a91481b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -412,6 +412,8 @@ impl Step for Rustc { let gcc_lld_dir = dst_dir.join("gcc-ld"); t!(fs::create_dir(&gcc_lld_dir)); builder.copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld", compiler.host))); + builder + .copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld64", compiler.host))); } // Copy over llvm-dwp if it's there diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 083d82cb414d8..3b2457ef9543f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -361,7 +361,7 @@ fn run_test( for debugging_option_str in &options.debugging_opts_strs { compiler.arg("-Z").arg(&debugging_option_str); } - if no_run && !compile_fail { + if no_run && !compile_fail && options.persist_doctests.is_none() { compiler.arg("--emit=metadata"); } compiler.arg("--target").arg(match target { diff --git a/src/test/run-make/doctests-keep-binaries/Makefile b/src/test/run-make/doctests-keep-binaries/Makefile new file mode 100644 index 0000000000000..273c8980b0224 --- /dev/null +++ b/src/test/run-make/doctests-keep-binaries/Makefile @@ -0,0 +1,21 @@ +include ../../run-make-fulldeps/tools.mk + +# Check that valid binaries are persisted by running them, regardless of whether the --run or --no-run option is used. + +all: run no_run + +run: + mkdir -p $(TMPDIR)/doctests + $(RUSTC) --crate-type rlib t.rs + $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs + $(TMPDIR)/doctests/t_rs_2_0/rust_out + $(TMPDIR)/doctests/t_rs_8_0/rust_out + rm -rf $(TMPDIR)/doctests + +no_run: + mkdir -p $(TMPDIR)/doctests + $(RUSTC) --crate-type rlib t.rs + $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs --no-run + $(TMPDIR)/doctests/t_rs_2_0/rust_out + $(TMPDIR)/doctests/t_rs_8_0/rust_out + rm -rf $(TMPDIR)/doctests diff --git a/src/test/run-make/doctests-keep-binaries/t.rs b/src/test/run-make/doctests-keep-binaries/t.rs new file mode 100644 index 0000000000000..c38cf0a0b25d4 --- /dev/null +++ b/src/test/run-make/doctests-keep-binaries/t.rs @@ -0,0 +1,11 @@ +/// Fungle the foople. +/// ``` +/// t::foople(); +/// ``` +pub fn foople() {} + +/// Flomble the florp +/// ``` +/// t::florp(); +/// ``` +pub fn florp() {} diff --git a/src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs b/src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs new file mode 100644 index 0000000000000..4060c409355a1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs @@ -0,0 +1,10 @@ +#[non_exhaustive] +pub enum E1 {} + +#[non_exhaustive] +pub enum E2 { A, B } + +#[non_exhaustive] +pub enum E3 { C } + +pub enum E4 { D } diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/issue-87097.rs rename to src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/issue-87097.stderr rename to src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87426.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/issue-87426.rs rename to src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.rs b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.rs new file mode 100644 index 0000000000000..035c658302745 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.rs @@ -0,0 +1,35 @@ +// edition:2021 + +enum SingleVariant { + A +} + +struct TestStruct { + x: i32, + y: i32, + z: i32, +} + +fn main() { + let sv = SingleVariant::A; + let condition = true; + // sv should not be captured as it is a SingleVariant + let _a = || { + match sv { + SingleVariant::A if condition => (), + _ => () + } + }; + let mut mut_sv = sv; + _a(); + + // ts should be captured + let ts = TestStruct { x: 1, y: 1, z: 1 }; + let _b = || { match ts { + TestStruct{ x: 1, .. } => (), + _ => () + }}; + let mut mut_ts = ts; + //~^ ERROR: cannot move out of `ts` because it is borrowed + _b(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.stderr new file mode 100644 index 0000000000000..b9d2316206ecb --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.stderr @@ -0,0 +1,17 @@ +error[E0505]: cannot move out of `ts` because it is borrowed + --> $DIR/match-edge-cases.rs:32:22 + | +LL | let _b = || { match ts { + | -- -- borrow occurs due to use in closure + | | + | borrow of `ts` occurs here +... +LL | let mut mut_ts = ts; + | ^^ move out of `ts` occurs here +LL | +LL | _b(); + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs new file mode 100644 index 0000000000000..318673ef847e5 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs @@ -0,0 +1,54 @@ +// edition:2021 + +// aux-build:match_non_exhaustive_lib.rs + +/* The error message for non-exhaustive matches on non-local enums + * marked as non-exhaustive should mention the fact that the enum + * is marked as non-exhaustive (issue #85227). + */ + +// Ignore non_exhaustive in the same crate +#[non_exhaustive] +enum L1 { A, B } +enum L2 { C } + +extern crate match_non_exhaustive_lib; +use match_non_exhaustive_lib::{E1, E2, E3, E4}; + +fn foo() -> (L1, L2) {todo!()} +fn bar() -> (E1, E2, E3, E4) {todo!()} + +fn main() { + let (l1, l2) = foo(); + // No error for enums defined in this crate + let _a = || { match l1 { L1::A => (), L1::B => () } }; + // (except if the match is already non-exhaustive) + let _b = || { match l1 { L1::A => () } }; + //~^ ERROR: non-exhaustive patterns: `B` not covered [E0004] + + // l2 should not be captured as it is a non-exhaustive SingleVariant + // defined in this crate + let _c = || { match l2 { L2::C => (), _ => () } }; + let mut mut_l2 = l2; + _c(); + + // E1 is not visibly uninhabited from here + let (e1, e2, e3, e4) = bar(); + let _d = || { match e1 {} }; + //~^ ERROR: non-exhaustive patterns: type `E1` is non-empty [E0004] + let _e = || { match e2 { E2::A => (), E2::B => () } }; + //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004] + let _f = || { match e2 { E2::A => (), E2::B => (), _ => () } }; + + // e3 should be captured as it is a non-exhaustive SingleVariant + // defined in another crate + let _g = || { match e3 { E3::C => (), _ => () } }; + let mut mut_e3 = e3; + //~^ ERROR: cannot move out of `e3` because it is borrowed + _g(); + + // e4 should not be captured as it is a SingleVariant + let _h = || { match e4 { E4::D => (), _ => () } }; + let mut mut_e4 = e4; + _h(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr new file mode 100644 index 0000000000000..91ffe1a47f413 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr @@ -0,0 +1,50 @@ +error[E0004]: non-exhaustive patterns: `B` not covered + --> $DIR/non-exhaustive-match.rs:26:25 + | +LL | enum L1 { A, B } + | ---------------- + | | | + | | not covered + | `L1` defined here +... +LL | let _b = || { match l1 { L1::A => () } }; + | ^^ pattern `B` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `L1` + +error[E0004]: non-exhaustive patterns: type `E1` is non-empty + --> $DIR/non-exhaustive-match.rs:37:25 + | +LL | let _d = || { match e1 {} }; + | ^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `E1`, which is marked as non-exhaustive + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/non-exhaustive-match.rs:39:25 + | +LL | let _e = || { match e2 { E2::A => (), E2::B => () } }; + | ^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `E2`, which is marked as non-exhaustive + +error[E0505]: cannot move out of `e3` because it is borrowed + --> $DIR/non-exhaustive-match.rs:46:22 + | +LL | let _g = || { match e3 { E3::C => (), _ => () } }; + | -- -- borrow occurs due to use in closure + | | + | borrow of `e3` occurs here +LL | let mut mut_e3 = e3; + | ^^ move out of `e3` occurs here +LL | +LL | _g(); + | -- borrow later used here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0004, E0505. +For more information about an error, try `rustc --explain E0004`. diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs rename to src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr rename to src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs rename to src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr rename to src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr diff --git a/src/test/ui/generic-associated-types/issue-87748.rs b/src/test/ui/generic-associated-types/issue-87748.rs new file mode 100644 index 0000000000000..93c3b3937cb81 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87748.rs @@ -0,0 +1,30 @@ +// Checks that we properly add implied bounds from unnormalized projections in +// inputs when typechecking functions. + +// check-pass + +#![feature(generic_associated_types)] + +trait MyTrait { + type Assoc<'a, 'b> where 'b: 'a; + fn do_sth(arg: Self::Assoc<'_, '_>); +} + +struct A; +struct B; +struct C; + +impl MyTrait for A { + type Assoc<'a, 'b> where 'b: 'a = u32; + fn do_sth(_: u32) {} +} +impl MyTrait for B { + type Assoc<'a, 'b> where 'b: 'a = u32; + fn do_sth(_: Self::Assoc<'_, '_>) {} +} +impl MyTrait for C { + type Assoc<'a, 'b> where 'b: 'a = u32; + fn do_sth(_: Self::Assoc<'static, 'static>) {} +} + +fn main () {} diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.rs b/src/test/ui/type-alias-impl-trait/static-const-types.rs new file mode 100644 index 0000000000000..f630d27833503 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/static-const-types.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// FIXME: This should compile, but it currently doesn't + +use std::fmt::Debug; + +type Foo = impl Debug; +//~^ ERROR: could not find defining uses + +static FOO1: Foo = 22_u32; +//~^ ERROR: mismatched types [E0308] +const FOO2: Foo = 22_u32; +//~^ ERROR: mismatched types [E0308] + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.stderr b/src/test/ui/type-alias-impl-trait/static-const-types.stderr new file mode 100644 index 0000000000000..72083d014fe3a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/static-const-types.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/static-const-types.rs:11:20 + | +LL | type Foo = impl Debug; + | ---------- the expected opaque type +... +LL | static FOO1: Foo = 22_u32; + | ^^^^^^ expected opaque type, found `u32` + | + = note: expected opaque type `impl Debug` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/static-const-types.rs:13:19 + | +LL | type Foo = impl Debug; + | ---------- the expected opaque type +... +LL | const FOO2: Foo = 22_u32; + | ^^^^^^ expected opaque type, found `u32` + | + = note: expected opaque type `impl Debug` + found type `u32` + +error: could not find defining uses + --> $DIR/static-const-types.rs:8:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/unsized/param-mentioned-by-different-field.rs b/src/test/ui/unsized/param-mentioned-by-different-field.rs new file mode 100644 index 0000000000000..cda94b306d333 --- /dev/null +++ b/src/test/ui/unsized/param-mentioned-by-different-field.rs @@ -0,0 +1,10 @@ +// We must not allow this with our current setup as `T` +// is mentioned both in the tail of `Foo` and by another +// field. +struct Foo(Box, T); + +fn main() { + let x: Foo<[u8; 1]> = Foo(Box::new([2]), [3]); + let y: &Foo<[u8]> = &x; //~ ERROR mismatched types + assert_eq!(y.0.len(), 1); +} diff --git a/src/test/ui/unsized/param-mentioned-by-different-field.stderr b/src/test/ui/unsized/param-mentioned-by-different-field.stderr new file mode 100644 index 0000000000000..d18fa6456f3ee --- /dev/null +++ b/src/test/ui/unsized/param-mentioned-by-different-field.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/param-mentioned-by-different-field.rs:8:25 + | +LL | let y: &Foo<[u8]> = &x; + | ---------- ^^ expected slice `[u8]`, found array `[u8; 1]` + | | + | expected due to this + | + = note: expected reference `&Foo<[u8]>` + found reference `&Foo<[u8; 1]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/triagebot.toml b/triagebot.toml index 81c6719647fc1..1e4df4d3fb79a 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -102,6 +102,8 @@ message_on_add = """\ - Needs `I-nominated`? """ message_on_remove = "Issue #{number}'s prioritization request has been removed." +message_on_close = "Issue #{number} has been closed while requested for prioritization." +message_on_reopen = "Issue #{number} has been reopened." [notify-zulip."T-rustdoc"] required_labels = ["I-nominated"]