diff --git a/RELEASES.md b/RELEASES.md index 7479735012cc9..ea6ae46b0edb7 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -5,7 +5,7 @@ Language -------- - [Stabilize `#[derive(Default)]` on enums with a `#[default]` variant][94457] -- [Stop validating some checks in dead code after functions with uninhabited return types][93313] +- [Teach flow sensitive checks that visibly uninhabited call expressions never return][93313] - [Fix constants not getting dropped if part of a diverging expression][94775] - [Support unit struct/enum variant in destructuring assignment][95380] - [Remove mutable_borrow_reservation_conflict lint and allow the code pattern][96268] @@ -75,6 +75,7 @@ Compatibility Notes - `cargo test` now passes `--target` to `rustdoc` if the specified target is the same as the host target. [#10594](https://github.com/rust-lang/cargo/pull/10594) +- [rustdoc: doctests are now run on unexported `macro_rules!` macros, matching other private items][96630] - [rustdoc: Remove .woff font files][96279] - [Enforce Copy bounds for repeat elements while considering lifetimes][95819] @@ -109,6 +110,7 @@ and related tools. [96393]: https://github.com/rust-lang/rust/pull/96393/ [96436]: https://github.com/rust-lang/rust/pull/96436/ [96557]: https://github.com/rust-lang/rust/pull/96557/ +[96630]: https://github.com/rust-lang/rust/pull/96630/ [`bool::then_some`]: https://doc.rust-lang.org/stable/std/primitive.bool.html#method.then_some [`f32::total_cmp`]: https://doc.rust-lang.org/stable/std/primitive.f32.html#method.total_cmp diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 20b9ed9cd7356..d290752614c29 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -334,7 +334,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut local_visitor = FindInferSourceVisitor::new(&self, typeck_results, arg); if let Some(body_id) = body_id { let expr = self.tcx.hir().expect_expr(body_id.hir_id); - debug!(?expr); local_visitor.visit_expr(expr); } @@ -550,6 +549,7 @@ impl<'tcx> InferSourceKind<'tcx> { } } +#[derive(Debug)] struct InsertableGenericArgs<'tcx> { insert_span: Span, substs: SubstsRef<'tcx>, @@ -735,10 +735,20 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { return self.path_inferred_subst_iter(expr.hir_id, substs, path); } } - hir::ExprKind::Struct(path, _, _) => { + // FIXME(#98711): Ideally we would also deal with type relative + // paths here, even if that is quite rare. + // + // See the `need_type_info/expr-struct-type-relative-gat.rs` test + // for an example where that would be needed. + // + // However, the `type_dependent_def_id` for `Self::Output` in an + // impl is currently the `DefId` of `Output` in the trait definition + // which makes this somewhat difficult and prevents us from just + // using `self.path_inferred_subst_iter` here. + hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _) => { if let Some(ty) = self.opt_node_type(expr.hir_id) { if let ty::Adt(_, substs) = ty.kind() { - return self.path_inferred_subst_iter(expr.hir_id, substs, path); + return Box::new(self.resolved_path_inferred_subst_iter(path, substs)); } } } @@ -945,6 +955,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { intravisit::walk_body(self, body); } + #[instrument(level = "debug", skip(self))] fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { let tcx = self.infcx.tcx; match expr.kind { @@ -959,9 +970,9 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { _ => intravisit::walk_expr(self, expr), } - for InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } in - self.expr_inferred_subst_iter(expr) - { + for args in self.expr_inferred_subst_iter(expr) { + debug!(?args); + let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args; let generics = tcx.generics_of(generics_def_id); if let Some(argument_index) = generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg)) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index d5075537cedda..5ad5692e7623c 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -156,6 +156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index); } + #[instrument(level = "debug", skip(self))] pub(in super::super) fn write_resolution( &self, hir_id: hir::HirId, @@ -164,8 +165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, r); } + #[instrument(level = "debug", skip(self))] pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { - debug!("write_method_call(hir_id={:?}, method={:?})", hir_id, method); self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); self.write_substs(hir_id, method.substs); diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs index a476799b70d6c..1757e37ec0e2f 100644 --- a/library/core/src/iter/traits/exact_size.rs +++ b/library/core/src/iter/traits/exact_size.rs @@ -66,13 +66,15 @@ /// /// // And now we can use it! /// -/// let counter = Counter::new(); +/// let mut counter = Counter::new(); /// /// assert_eq!(5, counter.len()); +/// let _ = counter.next(); +/// assert_eq!(4, counter.len()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait ExactSizeIterator: Iterator { - /// Returns the exact length of the iterator. + /// Returns the exact remaining length of the iterator. /// /// The implementation ensures that the iterator will return exactly `len()` /// more times a [`Some(T)`] value, before returning [`None`]. @@ -93,9 +95,11 @@ pub trait ExactSizeIterator: Iterator { /// /// ``` /// // a finite range knows exactly how many times it will iterate - /// let five = 0..5; + /// let mut range = 0..5; /// - /// assert_eq!(5, five.len()); + /// assert_eq!(5, range.len()); + /// let _ = range.next(); + /// assert_eq!(4, range.len()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 326b98ec947d2..275412b57b55f 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -177,9 +177,11 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3]; - /// let iter = a.iter(); + /// let mut iter = a.iter(); /// /// assert_eq!((3, Some(3)), iter.size_hint()); + /// let _ = iter.next(); + /// assert_eq!((2, Some(2)), iter.size_hint()); /// ``` /// /// A more complex example: diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 8000e60f64d47..6ead79ef040a9 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -866,6 +866,7 @@ def bootstrap(help_triggered): parser = argparse.ArgumentParser(description='Build rust') parser.add_argument('--config') + parser.add_argument('--build-dir') parser.add_argument('--build') parser.add_argument('--color', choices=['always', 'never', 'auto']) parser.add_argument('--clean', action='store_true') @@ -915,7 +916,7 @@ def bootstrap(help_triggered): build.check_vendored_status() - build_dir = build.get_toml('build-dir', 'build') or 'build' + build_dir = args.build_dir or build.get_toml('build-dir', 'build') or 'build' build.build_dir = os.path.abspath(build_dir) with open(os.path.join(build.rust_root, "src", "stage0.json")) as f: diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 14607741932ea..2fc18c9e79e32 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -857,7 +857,7 @@ impl Config { let build = toml.build.unwrap_or_default(); set(&mut config.initial_rustc, build.rustc.map(PathBuf::from)); - set(&mut config.out, build.build_dir.map(PathBuf::from)); + set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from))); // NOTE: Bootstrap spawns various commands with different working directories. // To avoid writing to random places on the file system, `config.out` needs to be an absolute path. if !config.out.is_absolute() { diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 8182d2bf8fb3b..74ec9cab5ca97 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1044,12 +1044,6 @@ impl Step for RustAnalyzer { } fn run(self, builder: &Builder<'_>) -> Option { - // This prevents rust-analyzer from being built for "dist" or "install" - // on the stable/beta channels. It is a nightly-only tool and should - // not be included. - if !builder.build.unstable_features() { - return None; - } let compiler = self.compiler; let target = self.target; diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 9d4bb978bdc4d..7ebae55efc168 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -51,6 +51,7 @@ pub struct Flags { pub host: Option>, pub target: Option>, pub config: Option, + pub build_dir: Option, pub jobs: Option, pub cmd: Subcommand, pub incremental: bool, @@ -174,6 +175,12 @@ To learn more about a subcommand, run `./x.py -h`", opts.optflagmulti("v", "verbose", "use verbose output (-vv for very verbose)"); opts.optflag("i", "incremental", "use incremental compilation"); opts.optopt("", "config", "TOML configuration file for build", "FILE"); + opts.optopt( + "", + "build-dir", + "Build directory, overrides `build.build-dir` in `config.toml`", + "DIR", + ); opts.optopt("", "build", "build target of the stage0 compiler", "BUILD"); opts.optmulti("", "host", "host targets to build", "HOST"); opts.optmulti("", "target", "target targets to build", "TARGET"); @@ -649,6 +656,7 @@ Arguments: None }, config: matches.opt_str("config").map(PathBuf::from), + build_dir: matches.opt_str("build-dir").map(PathBuf::from), jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")), cmd, incremental: matches.opt_present("incremental"), diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 905fa431d29d1..5be6841e988ae 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -780,7 +780,7 @@ tool_extended!((self, builder), // and this is close enough for now. RustDemangler, rust_demangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, tool_std=true, {}; Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, in_tree=true, {}; - RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, submodule="rust-analyzer", {}; + RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=true, submodule="rust-analyzer", {}; ); impl<'a> Builder<'a> { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 12467001271fd..6ee725edcfc1d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -167,7 +167,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>( .collect_referenced_late_bound_regions(&poly_trait_ref) .into_iter() .filter_map(|br| match br { - ty::BrNamed(_, name) => Some(GenericParamDef { + ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime { outlives: vec![] }, }), diff --git a/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs b/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs new file mode 100644 index 0000000000000..22cbeae72662a --- /dev/null +++ b/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs @@ -0,0 +1,9 @@ +/// When reexporting this function, make sure the anonymous lifetimes are not rendered. +/// +/// https://github.com/rust-lang/rust/issues/98697 +pub fn repro() +where + F: Fn(&str), +{ + unimplemented!() +} diff --git a/src/test/rustdoc/issue-98697.rs b/src/test/rustdoc/issue-98697.rs new file mode 100644 index 0000000000000..25ab55acd7747 --- /dev/null +++ b/src/test/rustdoc/issue-98697.rs @@ -0,0 +1,13 @@ +// aux-build:issue-98697-reexport-with-anonymous-lifetime.rs +// ignore-cross-compile + +// When reexporting a function with a HRTB with anonymous lifetimes, +// make sure the anonymous lifetimes are not rendered. +// +// https://github.com/rust-lang/rust/issues/98697 + +extern crate issue_98697_reexport_with_anonymous_lifetime; + +// @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro() where F: Fn(&str)' +// @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<' +pub use issue_98697_reexport_with_anonymous_lifetime::repro; diff --git a/src/test/ui/const-generics/issue-46511.rs b/src/test/ui/const-generics/issue-46511.rs new file mode 100644 index 0000000000000..71c50e2f3f7f3 --- /dev/null +++ b/src/test/ui/const-generics/issue-46511.rs @@ -0,0 +1,8 @@ +// check-fail + +struct Foo<'a> //~ ERROR parameter `'a` is never used [E0392] +{ + _a: [u8; std::mem::size_of::<&'a mut u8>()] //~ ERROR a non-static lifetime is not allowed in a `const` +} + +pub fn main() {} diff --git a/src/test/ui/const-generics/issue-46511.stderr b/src/test/ui/const-generics/issue-46511.stderr new file mode 100644 index 0000000000000..b21afa56dcbfc --- /dev/null +++ b/src/test/ui/const-generics/issue-46511.stderr @@ -0,0 +1,21 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/issue-46511.rs:5:35 + | +LL | _a: [u8; std::mem::size_of::<&'a mut u8>()] + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0392]: parameter `'a` is never used + --> $DIR/issue-46511.rs:3:12 + | +LL | struct Foo<'a> + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0658. +For more information about an error, try `rustc --explain E0392`. diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.rs b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.rs new file mode 100644 index 0000000000000..42af9fa8d113a --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.rs @@ -0,0 +1,21 @@ +trait Foo { + type Output; + + fn baz() -> Self::Output; +} + +fn needs_infer() {} + +enum Bar { + Variant {} +} + +impl Foo for u8 { + type Output = Bar; + fn baz() -> Self::Output { + needs_infer(); //~ ERROR type annotations needed + Self::Output::Variant {} + } +} + +fn main() {} diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr new file mode 100644 index 0000000000000..68ecb38134837 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative-enum.rs:16:9 + | +LL | needs_infer(); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer` + | +help: consider specifying the generic argument + | +LL | needs_infer::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.rs b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.rs new file mode 100644 index 0000000000000..bcd29bb4e3495 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.rs @@ -0,0 +1,21 @@ +#![feature(generic_associated_types)] + +trait Foo { + type Output; + + fn baz(); +} + +enum Bar { + Simple {}, + Generic(T), +} + +impl Foo for u8 { + type Output = Bar; + fn baz() { + Self::Output::Simple {}; //~ ERROR type annotations needed + } +} + +fn main() {} diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr new file mode 100644 index 0000000000000..65a75b68c1f08 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative-gat.rs:17:9 + | +LL | Self::Output::Simple {}; + | ^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated type `Output` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative.rs b/src/test/ui/inference/need_type_info/expr-struct-type-relative.rs new file mode 100644 index 0000000000000..c3ece2b16cf08 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative.rs @@ -0,0 +1,21 @@ +// regression test for #98598 + +trait Foo { + type Output; + + fn baz() -> Self::Output; +} + +fn needs_infer() {} + +struct Bar {} + +impl Foo for u8 { + type Output = Bar; + fn baz() -> Self::Output { + needs_infer(); //~ ERROR type annotations needed + Self::Output {} + } +} + +fn main() {} diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative.stderr b/src/test/ui/inference/need_type_info/expr-struct-type-relative.stderr new file mode 100644 index 0000000000000..397d8e7be04ff --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative.rs:16:9 + | +LL | needs_infer(); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer` + | +help: consider specifying the generic argument + | +LL | needs_infer::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 6338e467055cd..efe3f2b618be3 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -184,7 +184,7 @@ static PKG_INSTALLERS: &[&str] = &["x86_64-apple-darwin", "aarch64-apple-darwin" static MINGW: &[&str] = &["i686-pc-windows-gnu", "x86_64-pc-windows-gnu"]; -static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview", "rust-analyzer-preview"]; +static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview"]; macro_rules! t { ($e:expr) => { @@ -403,6 +403,7 @@ impl Builder { rename("rustfmt", "rustfmt-preview"); rename("clippy", "clippy-preview"); rename("miri", "miri-preview"); + rename("rust-analyzer", "rust-analyzer-preview"); } fn rust_package(&mut self, manifest: &Manifest) -> Package { diff --git a/triagebot.toml b/triagebot.toml index e165dd4f17c15..ba9ed20cc64a2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -324,4 +324,4 @@ cc = ["@rust-lang/rustfmt"] [mentions."compiler/rustc_middle/src/mir/syntax.rs"] message = "This PR changes MIR" -cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco"] +cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval"]