From 86bdb3ed0912b6a8810815342a5ab570cac56ce5 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Tue, 9 Aug 2022 18:41:42 +0100 Subject: [PATCH 01/14] Rustdoc-Json: Add `Path` type for traits. Closes #100106 --- src/etc/check_missing_items.py | 58 ++++++++++---------- src/librustdoc/json/conversions.rs | 46 +++++++--------- src/rustdoc-json-types/lib.rs | 31 +++++++---- src/test/rustdoc-json/fns/generic_args.rs | 12 ++-- src/test/rustdoc-json/fns/generic_returns.rs | 2 +- src/test/rustdoc-json/fns/generics.rs | 6 +- src/test/rustdoc-json/traits/supertrait.rs | 10 ++-- src/test/rustdoc-json/type/dyn.rs | 23 ++++---- src/test/rustdoc-json/type/hrtb.rs | 2 +- 9 files changed, 96 insertions(+), 94 deletions(-) diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py index a705e2384959f..ce06a79a21c3f 100644 --- a/src/etc/check_missing_items.py +++ b/src/etc/check_missing_items.py @@ -57,7 +57,7 @@ def check_generic_bound(bound): if "trait_bound" in bound: for param in bound["trait_bound"]["generic_params"]: check_generic_param(param) - check_type(bound["trait_bound"]["trait"]) + check_path(bound["trait_bound"]["trait"]) def check_decl(decl): @@ -66,35 +66,35 @@ def check_decl(decl): if decl["output"]: check_type(decl["output"]) +def check_path(path): + args = path["args"] + if args: + if "angle_bracketed" in args: + for arg in args["angle_bracketed"]["args"]: + if "type" in arg: + check_type(arg["type"]) + elif "const" in arg: + check_type(arg["const"]["type"]) + for binding in args["angle_bracketed"]["bindings"]: + if "equality" in binding["binding"]: + term = binding["binding"]["equality"] + if "type" in term: check_type(term["type"]) + elif "const" in term: check_type(term["const"]) + elif "constraint" in binding["binding"]: + for bound in binding["binding"]["constraint"]: + check_generic_bound(bound) + elif "parenthesized" in args: + for input_ty in args["parenthesized"]["inputs"]: + check_type(input_ty) + if args["parenthesized"]["output"]: + check_type(args["parenthesized"]["output"]) + if not valid_id(path["id"]): + print("Type contained an invalid ID:", path["id"]) + sys.exit(1) def check_type(ty): if ty["kind"] == "resolved_path": - for bound in ty["inner"]["param_names"]: - check_generic_bound(bound) - args = ty["inner"]["args"] - if args: - if "angle_bracketed" in args: - for arg in args["angle_bracketed"]["args"]: - if "type" in arg: - check_type(arg["type"]) - elif "const" in arg: - check_type(arg["const"]["type"]) - for binding in args["angle_bracketed"]["bindings"]: - if "equality" in binding["binding"]: - term = binding["binding"]["equality"] - if "type" in term: check_type(term["type"]) - elif "const" in term: check_type(term["const"]) - elif "constraint" in binding["binding"]: - for bound in binding["binding"]["constraint"]: - check_generic_bound(bound) - elif "parenthesized" in args: - for input_ty in args["parenthesized"]["inputs"]: - check_type(input_ty) - if args["parenthesized"]["output"]: - check_type(args["parenthesized"]["output"]) - if not valid_id(ty["inner"]["id"]): - print("Type contained an invalid ID:", ty["inner"]["id"]) - sys.exit(1) + check_path(ty["inner"]) elif ty["kind"] == "tuple": for ty in ty["inner"]: check_type(ty) @@ -111,7 +111,7 @@ def check_type(ty): check_decl(ty["inner"]["decl"]) elif ty["kind"] == "qualified_path": check_type(ty["inner"]["self_type"]) - check_type(ty["inner"]["trait"]) + check_path(ty["inner"]["trait"]) work_list = set([crate["root"]]) @@ -174,7 +174,7 @@ def check_type(ty): elif item["kind"] == "impl": check_generics(item["inner"]["generics"]) if item["inner"]["trait"]: - check_type(item["inner"]["trait"]) + check_path(item["inner"]["trait"]) if item["inner"]["blanket_impl"]: check_type(item["inner"]["blanket_impl"]) check_type(item["inner"]["for"]) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 8caba8cb9029c..9795504175cd5 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -428,10 +428,8 @@ impl FromWithTcx for GenericBound { use clean::GenericBound::*; match bound { TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => { - // FIXME: should `trait_` be a clean::Path equivalent in JSON? - let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx); GenericBound::TraitBound { - trait_, + trait_: trait_.into_tcx(tcx), generic_params: generic_params.into_tcx(tcx), modifier: from_trait_bound_modifier(modifier), } @@ -460,12 +458,7 @@ impl FromWithTcx for Type { }; match ty { - clean::Type::Path { path } => Type::ResolvedPath { - name: path.whole_name(), - id: from_item_id(path.def_id().into(), tcx), - args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))), - param_names: Vec::new(), - }, + clean::Type::Path { path } => Type::ResolvedPath(path.into_tcx(tcx)), clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait { lifetime: lt.map(convert_lifetime), traits: bounds.into_tcx(tcx), @@ -487,16 +480,22 @@ impl FromWithTcx for Type { mutable: mutability == ast::Mutability::Mut, type_: Box::new((*type_).into_tcx(tcx)), }, - QPath { assoc, self_type, trait_, .. } => { - // FIXME: should `trait_` be a clean::Path equivalent in JSON? - let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx); - Type::QualifiedPath { - name: assoc.name.to_string(), - args: Box::new(assoc.args.clone().into_tcx(tcx)), - self_type: Box::new((*self_type).into_tcx(tcx)), - trait_: Box::new(trait_), - } - } + QPath { assoc, self_type, trait_, .. } => Type::QualifiedPath { + name: assoc.name.to_string(), + args: Box::new(assoc.args.clone().into_tcx(tcx)), + self_type: Box::new((*self_type).into_tcx(tcx)), + trait_: trait_.into_tcx(tcx), + }, + } + } +} + +impl FromWithTcx for Path { + fn from_tcx(path: clean::Path, tcx: TyCtxt<'_>) -> Path { + Path { + name: path.whole_name(), + id: from_item_id(path.def_id().into(), tcx), + args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))), } } } @@ -565,10 +564,7 @@ impl FromWithTcx for PolyTrait { clean::PolyTrait { trait_, generic_params }: clean::PolyTrait, tcx: TyCtxt<'_>, ) -> Self { - PolyTrait { - trait_: clean::Type::Path { path: trait_ }.into_tcx(tcx), - generic_params: generic_params.into_tcx(tcx), - } + PolyTrait { trait_: trait_.into_tcx(tcx), generic_params: generic_params.into_tcx(tcx) } } } @@ -576,8 +572,6 @@ impl FromWithTcx for Impl { fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self { let provided_trait_methods = impl_.provided_trait_methods(tcx); let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_; - // FIXME: should `trait_` be a clean::Path equivalent in JSON? - let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx)); // FIXME: use something like ImplKind in JSON? let (synthetic, blanket_impl) = match kind { clean::ImplKind::Normal | clean::ImplKind::FakeVaradic => (false, None), @@ -595,7 +589,7 @@ impl FromWithTcx for Impl { .into_iter() .map(|x| x.to_string()) .collect(), - trait_, + trait_: trait_.map(|path| path.into_tcx(tcx)), for_: for_.into_tcx(tcx), items: ids(items, tcx), negative: negative_polarity, diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index bd4ea98441d66..c9b08fc200658 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 17; +pub const FORMAT_VERSION: u32 = 18; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -133,7 +133,7 @@ pub struct DynTrait { /// A trait and potential HRTBs pub struct PolyTrait { #[serde(rename = "trait")] - pub trait_: Type, + pub trait_: Path, /// Used for Higher-Rank Trait Bounds (HRTBs) /// ```text /// dyn for<'a> Fn() -> &'a i32" @@ -447,7 +447,7 @@ pub enum WherePredicate { pub enum GenericBound { TraitBound { #[serde(rename = "trait")] - trait_: Type, + trait_: Path, /// Used for Higher-Rank Trait Bounds (HRTBs) /// ```text /// where F: for<'a, 'b> Fn(&'a u8, &'b u8) @@ -481,12 +481,7 @@ pub enum Term { #[serde(tag = "kind", content = "inner")] pub enum Type { /// Structs, enums, and traits - ResolvedPath { - name: String, - id: Id, - args: Option>, - param_names: Vec, - }, + ResolvedPath(Path), DynTrait(DynTrait), /// Parameterized types Generic(String), @@ -527,10 +522,24 @@ pub enum Type { args: Box, self_type: Box, #[serde(rename = "trait")] - trait_: Box, + trait_: Path, }, } +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Path { + pub name: String, + pub id: Id, + /// Generic arguments to the type + /// ```test + /// std::borrow::Cow<'static, str> + /// ^^^^^^^^^^^^^^ + /// | + /// this part + /// ``` + pub args: Option>, +} + #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct FunctionPointer { pub decl: FnDecl, @@ -574,7 +583,7 @@ pub struct Impl { pub generics: Generics, pub provided_trait_methods: Vec, #[serde(rename = "trait")] - pub trait_: Option, + pub trait_: Option, #[serde(rename = "for")] pub for_: Type, pub items: Vec, diff --git a/src/test/rustdoc-json/fns/generic_args.rs b/src/test/rustdoc-json/fns/generic_args.rs index 69150443c29dc..98ba8e99d820c 100644 --- a/src/test/rustdoc-json/fns/generic_args.rs +++ b/src/test/rustdoc-json/fns/generic_args.rs @@ -14,7 +14,7 @@ pub trait GenericFoo<'a> {} // @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].name" '"F"' // @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.default" 'null' // @count - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" '$foo' +// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo' // @count - "$.index[*][?(@.name=='generics')].inner.decl.inputs[*]" 1 // @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][0]" '"f"' // @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].kind" '"generic"' @@ -24,12 +24,12 @@ pub fn generics(f: F) {} // @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.where_predicates" "[]" // @count - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[*]" 1 // @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].name" '"impl Foo"' -// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $foo +// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo // @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[*]" 1 // @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][0]" '"f"' // @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].kind" '"impl_trait"' // @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[*]" 1 -// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $foo +// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $foo pub fn impl_trait(f: impl Foo) {} // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 3 @@ -43,11 +43,11 @@ pub fn impl_trait(f: impl Foo) {} // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F", "kind": "generic"}' // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo +// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.type" '{"inner": "G", "kind": "generic"}' // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.inner.id" $generic_foo +// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\" // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' @@ -57,7 +57,7 @@ pub fn impl_trait(f: impl Foo) {} // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.lifetime" \"\'b\" // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.type" '{"inner": "H", "kind": "generic"}' // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo +// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]" // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[*]" 1 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\" diff --git a/src/test/rustdoc-json/fns/generic_returns.rs b/src/test/rustdoc-json/fns/generic_returns.rs index 1a0f33fe3d28e..46f250a99b9b6 100644 --- a/src/test/rustdoc-json/fns/generic_returns.rs +++ b/src/test/rustdoc-json/fns/generic_returns.rs @@ -11,7 +11,7 @@ pub trait Foo {} // @is - "$.index[*][?(@.name=='get_foo')].inner.decl.inputs" [] // @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.kind" '"impl_trait"' // @count - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[*]" 1 -// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.inner.id" $foo +// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.id" $foo pub fn get_foo() -> impl Foo { Fooer {} } diff --git a/src/test/rustdoc-json/fns/generics.rs b/src/test/rustdoc-json/fns/generics.rs index e777fabaa52a7..e55e1e9400dc6 100644 --- a/src/test/rustdoc-json/fns/generics.rs +++ b/src/test/rustdoc-json/fns/generics.rs @@ -10,7 +10,7 @@ pub trait Wham {} // @count - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1 // @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"' // @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false -// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id +// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id // @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]' pub fn one_generic_param_fn(w: T) {} @@ -18,9 +18,9 @@ pub fn one_generic_param_fn(w: T) {} // @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1 // @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"' // @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true -// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id +// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id // @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1 // @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"' // @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"' -// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $wham_id +// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $wham_id pub fn one_synthetic_generic_param_fn(w: impl Wham) {} diff --git a/src/test/rustdoc-json/traits/supertrait.rs b/src/test/rustdoc-json/traits/supertrait.rs index 486a8e713f811..ce2f3912ba650 100644 --- a/src/test/rustdoc-json/traits/supertrait.rs +++ b/src/test/rustdoc-json/traits/supertrait.rs @@ -9,18 +9,18 @@ pub trait Loud {} // @set very_loud_id = - "$.index[*][?(@.name=='VeryLoud')].id" // @count - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.inner.id" $loud_id +// @is - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.id" $loud_id pub trait VeryLoud: Loud {} // @set sounds_good_id = - "$.index[*][?(@.name=='SoundsGood')].id" pub trait SoundsGood {} // @count - "$.index[*][?(@.name=='MetalBand')].inner.bounds[*]" 2 -// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.inner.id" $very_loud_id -// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.inner.id" $sounds_good_id +// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.id" $very_loud_id +// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.id" $sounds_good_id pub trait MetalBand: VeryLoud + SoundsGood {} // @count - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[*]" 2 -// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.inner.id" $very_loud_id -// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.inner.id" $sounds_good_id +// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.id" $very_loud_id +// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.id" $sounds_good_id pub trait DnabLatem: SoundsGood + VeryLoud {} diff --git a/src/test/rustdoc-json/type/dyn.rs b/src/test/rustdoc-json/type/dyn.rs index c18b54d1fdf0e..690dccc828704 100644 --- a/src/test/rustdoc-json/type/dyn.rs +++ b/src/test/rustdoc-json/type/dyn.rs @@ -21,10 +21,10 @@ use std::fmt::Debug; // @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].generic_params" [] // @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].generic_params" [] // @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].generic_params" [] -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.name" '"Fn"' -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.inner.name" '"Send"' -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.inner.name" '"Sync"' -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}' +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Fn"' +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Send"' +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.name" '"Sync"' +// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}' pub type SyncIntGen = Box i32 + Send + Sync + 'static>; // @is - "$.index[*][?(@.name=='RefFn')].kind" \"typedef\" @@ -36,14 +36,13 @@ pub type SyncIntGen = Box i32 + Send + Sync + 'static>; // @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.lifetime" null // @count - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[*]" 1 // @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.kind" '"resolved_path"' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.name" '"Fn"' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.inputs[0].kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.inputs[0].inner.lifetime" "\"'b\"" -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.output.kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.output.inner.lifetime" "\"'b\"" +// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.name" '"Fn"' +// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].kind" '"borrowed_ref"' +// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].inner.lifetime" "\"'b\"" +// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.kind" '"borrowed_ref"' +// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.inner.lifetime" "\"'b\"" pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32; -// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.name" '"Send"' -// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.inner.name" '"Debug"' +// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Send"' +// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Debug"' pub type WeirdOrder = Box; diff --git a/src/test/rustdoc-json/type/hrtb.rs b/src/test/rustdoc-json/type/hrtb.rs index 9311737be0fec..5b0c4caee2186 100644 --- a/src/test/rustdoc-json/type/hrtb.rs +++ b/src/test/rustdoc-json/type/hrtb.rs @@ -19,7 +19,7 @@ where // @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.lifetime" null // @count - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[*]" 1 // @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.inner.name" '"Fn"' +// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.name" '"Fn"' pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) { let zero = 0; f(&zero, &zero); From 0fb4ef6769dd2f5ccb3daf1e84c0afe75ca8c118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 10 Aug 2022 14:06:27 +0200 Subject: [PATCH 02/14] Suggest path separator when a dot is used on a trait --- .../rustc_resolve/src/late/diagnostics.rs | 53 ++++++++---- src/test/ui/resolve/issue-100365.rs | 50 +++++++++++ src/test/ui/resolve/issue-100365.stderr | 54 ++++++++++++ src/test/ui/resolve/issue-22692.rs | 59 ++++++++++++- src/test/ui/resolve/issue-22692.stderr | 85 ++++++++++++++++++- .../suggest-path-for-tuple-struct.stderr | 8 +- .../suggest-path-instead-of-mod-dot-item.rs | 52 ++++++++++++ ...uggest-path-instead-of-mod-dot-item.stderr | 82 +++++++++++++----- .../suggestions/assoc-const-as-field.stderr | 4 +- 9 files changed, 394 insertions(+), 53 deletions(-) create mode 100644 src/test/ui/resolve/issue-100365.rs create mode 100644 src/test/ui/resolve/issue-100365.stderr diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index cb133841bca5a..09c1f44826fa4 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -985,27 +985,45 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let ns = source.namespace(); let is_expected = &|res| source.is_expected(res); - let path_sep = |err: &mut Diagnostic, expr: &Expr| match expr.kind { - ExprKind::Field(_, ident) => { + let path_sep = |err: &mut Diagnostic, expr: &Expr, kind: DefKind| { + const MESSAGE: &str = "use the path separator to refer to an item"; + + let (lhs_span, rhs_span) = match &expr.kind { + ExprKind::Field(base, ident) => (base.span, ident.span), + ExprKind::MethodCall(_, receiver, _, span) => (receiver.span, *span), + _ => return false, + }; + + if lhs_span.eq_ctxt(rhs_span) { err.span_suggestion( - expr.span, - "use the path separator to refer to an item", - format!("{}::{}", path_str, ident), + lhs_span.between(rhs_span), + MESSAGE, + "::", Applicability::MaybeIncorrect, ); true - } - ExprKind::MethodCall(ref segment, ..) => { - let span = expr.span.with_hi(segment.ident.span.hi()); - err.span_suggestion( - span, - "use the path separator to refer to an item", - format!("{}::{}", path_str, segment.ident), + } else if kind == DefKind::Struct + && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span) + && let Ok(snippet) = self.r.session.source_map().span_to_snippet(lhs_source_span) + { + // The LHS is a type that originates from a macro call. + // We have to add angle brackets around it. + + err.span_suggestion_verbose( + lhs_source_span.until(rhs_span), + MESSAGE, + format!("<{snippet}>::"), Applicability::MaybeIncorrect, ); true + } else { + // Either we were unable to obtain the source span / the snippet or + // the LHS originates from a macro call and it is not a type and thus + // there is no way to replace `.` with `::` and still somehow suggest + // valid Rust code. + + false } - _ => false, }; let find_span = |source: &PathSource<'_>, err: &mut Diagnostic| { @@ -1027,7 +1045,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { match source { PathSource::Expr(Some( parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. }, - )) if path_sep(err, &parent) => {} + )) if path_sep(err, &parent, DefKind::Struct) => {} PathSource::Expr( None | Some(Expr { @@ -1143,8 +1161,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } } - (Res::Def(DefKind::Mod, _), PathSource::Expr(Some(parent))) => { - if !path_sep(err, &parent) { + ( + Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _), + PathSource::Expr(Some(parent)), + ) => { + if !path_sep(err, &parent, kind) { return false; } } diff --git a/src/test/ui/resolve/issue-100365.rs b/src/test/ui/resolve/issue-100365.rs new file mode 100644 index 0000000000000..1d8835036065b --- /dev/null +++ b/src/test/ui/resolve/issue-100365.rs @@ -0,0 +1,50 @@ +fn main() { + let addr = Into::.into([127, 0, 0, 1]); + //~^ ERROR expected value, found trait `Into` + //~| HELP use the path separator + + let _ = Into.into(()); + //~^ ERROR expected value, found trait `Into` + //~| HELP use the path separator + + let _ = Into::<()>.into; + //~^ ERROR expected value, found trait `Into` + //~| HELP use the path separator +} + +macro_rules! Trait { + () => { + ::std::iter::Iterator + //~^ ERROR expected value, found trait `std::iter::Iterator` + //~| ERROR expected value, found trait `std::iter::Iterator` + }; +} + +macro_rules! create { + () => { + Into::.into("") + //~^ ERROR expected value, found trait `Into` + //~| HELP use the path separator + }; +} + +fn interaction_with_macros() { + // + // Note that if the receiver is a macro call, we do not want to suggest to replace + // `.` with `::` as that would be a syntax error. + // Since the receiver is a trait and not a type, we cannot suggest to surround + // it with angle brackets. It would be interpreted as a trait object type void of + // `dyn` which is most likely not what the user intended to write. + // `<_ as Trait!()>::` is also not an option as it's equally syntactically invalid. + // + + Trait!().map(std::convert::identity); // no `help` here! + + Trait!().map; // no `help` here! + + // + // Ensure that the suggestion is shown for expressions inside of macro definitions. + // + + let _ = create!(); +} diff --git a/src/test/ui/resolve/issue-100365.stderr b/src/test/ui/resolve/issue-100365.stderr new file mode 100644 index 0000000000000..372d772666804 --- /dev/null +++ b/src/test/ui/resolve/issue-100365.stderr @@ -0,0 +1,54 @@ +error[E0423]: expected value, found trait `Into` + --> $DIR/issue-100365.rs:2:16 + | +LL | let addr = Into::.into([127, 0, 0, 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found trait `Into` + --> $DIR/issue-100365.rs:6:13 + | +LL | let _ = Into.into(()); + | ^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found trait `Into` + --> $DIR/issue-100365.rs:10:13 + | +LL | let _ = Into::<()>.into; + | ^^^^^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found trait `std::iter::Iterator` + --> $DIR/issue-100365.rs:17:9 + | +LL | ::std::iter::Iterator + | ^^^^^^^^^^^^^^^^^^^^^ not a value +... +LL | Trait!().map(std::convert::identity); // no `help` here! + | -------- in this macro invocation + | + = note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found trait `std::iter::Iterator` + --> $DIR/issue-100365.rs:17:9 + | +LL | ::std::iter::Iterator + | ^^^^^^^^^^^^^^^^^^^^^ not a value +... +LL | Trait!().map; // no `help` here! + | -------- in this macro invocation + | + = note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found trait `Into` + --> $DIR/issue-100365.rs:25:9 + | +LL | Into::.into("") + | ^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(); + | --------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/issue-22692.rs b/src/test/ui/resolve/issue-22692.rs index 1d8f442221df9..31a76261408ef 100644 --- a/src/test/ui/resolve/issue-22692.rs +++ b/src/test/ui/resolve/issue-22692.rs @@ -1,3 +1,60 @@ fn main() { - let _ = String.new(); //~ ERROR expected value, found struct `String` + let _ = String.new(); + //~^ ERROR expected value, found struct `String` + //~| HELP use the path separator + + let _ = String.default; + //~^ ERROR expected value, found struct `String` + //~| HELP use the path separator + + let _ = Vec::<()>.with_capacity(1); + //~^ ERROR expected value, found struct `Vec` + //~| HELP use the path separator +} + +macro_rules! Type { + () => { + ::std::cell::Cell + //~^ ERROR expected value, found struct `std::cell::Cell` + //~| ERROR expected value, found struct `std::cell::Cell` + //~| ERROR expected value, found struct `std::cell::Cell` + }; +} + +macro_rules! create { + (type method) => { + Vec.new() + //~^ ERROR expected value, found struct `Vec` + //~| HELP use the path separator + }; + (type field) => { + Vec.new + //~^ ERROR expected value, found struct `Vec` + //~| HELP use the path separator + }; + (macro method) => { + Type!().new(0) + //~^ HELP use the path separator + }; +} + +fn interaction_with_macros() { + // + // Verify that we do not only suggest to replace `.` with `::` if the receiver is a + // macro call but that we also correctly suggest to surround it with angle brackets. + // + + Type!().get(); + //~^ HELP use the path separator + + Type! {}.get; + //~^ HELP use the path separator + + // + // Ensure that the suggestion is shown for expressions inside of macro definitions. + // + + let _ = create!(type method); + let _ = create!(type field); + let _ = create!(macro method); } diff --git a/src/test/ui/resolve/issue-22692.stderr b/src/test/ui/resolve/issue-22692.stderr index e076419f68d47..6962aa161e92a 100644 --- a/src/test/ui/resolve/issue-22692.stderr +++ b/src/test/ui/resolve/issue-22692.stderr @@ -2,10 +2,87 @@ error[E0423]: expected value, found struct `String` --> $DIR/issue-22692.rs:2:13 | LL | let _ = String.new(); - | ^^^^^^---- - | | - | help: use the path separator to refer to an item: `String::new` + | ^^^^^^- help: use the path separator to refer to an item: `::` -error: aborting due to previous error +error[E0423]: expected value, found struct `String` + --> $DIR/issue-22692.rs:6:13 + | +LL | let _ = String.default; + | ^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-22692.rs:10:13 + | +LL | let _ = Vec::<()>.with_capacity(1); + | ^^^^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found struct `std::cell::Cell` + --> $DIR/issue-22692.rs:17:9 + | +LL | ::std::cell::Cell + | ^^^^^^^^^^^^^^^^^ +... +LL | Type!().get(); + | ------- in this macro invocation + | + = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | ::get(); + | ~~~~~~~~~~~ + +error[E0423]: expected value, found struct `std::cell::Cell` + --> $DIR/issue-22692.rs:17:9 + | +LL | ::std::cell::Cell + | ^^^^^^^^^^^^^^^^^ +... +LL | Type! {}.get; + | -------- in this macro invocation + | + = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | ::get; + | ~~~~~~~~~~~~ + +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-22692.rs:26:9 + | +LL | Vec.new() + | ^^^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(type method); + | -------------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-22692.rs:31:9 + | +LL | Vec.new + | ^^^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(type field); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found struct `std::cell::Cell` + --> $DIR/issue-22692.rs:17:9 + | +LL | ::std::cell::Cell + | ^^^^^^^^^^^^^^^^^ +... +LL | let _ = create!(macro method); + | --------------------- in this macro invocation + | + = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | ::new(0) + | ~~~~~~~~~~~ + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr b/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr index 957045ca74bb2..4764cf2db20e8 100644 --- a/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr +++ b/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr @@ -2,17 +2,13 @@ error[E0423]: expected value, found struct `SomeTupleStruct` --> $DIR/suggest-path-for-tuple-struct.rs:22:13 | LL | let _ = SomeTupleStruct.new(); - | ^^^^^^^^^^^^^^^---- - | | - | help: use the path separator to refer to an item: `SomeTupleStruct::new` + | ^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` error[E0423]: expected value, found struct `SomeRegularStruct` --> $DIR/suggest-path-for-tuple-struct.rs:24:13 | LL | let _ = SomeRegularStruct.new(); - | ^^^^^^^^^^^^^^^^^---- - | | - | help: use the path separator to refer to an item: `SomeRegularStruct::new` + | ^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs index 204a272402dd7..d5d6b13d62c28 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs @@ -16,44 +16,96 @@ pub mod a { fn h1() -> i32 { a.I //~^ ERROR expected value, found module `a` + //~| HELP use the path separator } fn h2() -> i32 { a.g() //~^ ERROR expected value, found module `a` + //~| HELP use the path separator } fn h3() -> i32 { a.b.J //~^ ERROR expected value, found module `a` + //~| HELP use the path separator } fn h4() -> i32 { a::b.J //~^ ERROR expected value, found module `a::b` + //~| HELP a constant with a similar name exists + //~| HELP use the path separator } fn h5() { a.b.f(); //~^ ERROR expected value, found module `a` + //~| HELP use the path separator let v = Vec::new(); v.push(a::b); //~^ ERROR expected value, found module `a::b` + //~| HELP a constant with a similar name exists } fn h6() -> i32 { a::b.f() //~^ ERROR expected value, found module `a::b` + //~| HELP a constant with a similar name exists + //~| HELP use the path separator } fn h7() { a::b //~^ ERROR expected value, found module `a::b` + //~| HELP a constant with a similar name exists } fn h8() -> i32 { a::b() //~^ ERROR expected function, found module `a::b` + //~| HELP a constant with a similar name exists +} + +macro_rules! module { + () => { + a + //~^ ERROR expected value, found module `a` + //~| ERROR expected value, found module `a` + }; +} + +macro_rules! create { + (method) => { + a.f() + //~^ ERROR expected value, found module `a` + //~| HELP use the path separator + }; + (field) => { + a.f + //~^ ERROR expected value, found module `a` + //~| HELP use the path separator + }; +} + +fn h9() { + // + // Note that if the receiver is a macro call, we do not want to suggest to replace + // `.` with `::` as that would be a syntax error. + // Since the receiver is a module and not a type, we cannot suggest to surround + // it with angle brackets. + // + + module!().g::<()>(); // no `help` here! + + module!().g; // no `help` here! + + // + // Ensure that the suggestion is shown for expressions inside of macro definitions. + // + + let _ = create!(method); + let _ = create!(field); } fn main() {} diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index 54b242123eb8f..a4ce0deeb70f5 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -2,28 +2,22 @@ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:17:5 | LL | a.I - | ^-- - | | - | help: use the path separator to refer to an item: `a::I` + | ^- help: use the path separator to refer to an item: `::` error[E0423]: expected value, found module `a` - --> $DIR/suggest-path-instead-of-mod-dot-item.rs:22:5 + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:23:5 | LL | a.g() - | ^-- - | | - | help: use the path separator to refer to an item: `a::g` + | ^- help: use the path separator to refer to an item: `::` error[E0423]: expected value, found module `a` - --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5 + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:29:5 | LL | a.b.J - | ^-- - | | - | help: use the path separator to refer to an item: `a::b` + | ^- help: use the path separator to refer to an item: `::` error[E0423]: expected value, found module `a::b` - --> $DIR/suggest-path-instead-of-mod-dot-item.rs:32:5 + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:35:5 | LL | pub const I: i32 = 1; | --------------------- similarly named constant `I` defined here @@ -34,22 +28,20 @@ LL | a::b.J help: use the path separator to refer to an item | LL | a::b::J - | + | ~~ help: a constant with a similar name exists | LL | a::I.J | ~ error[E0423]: expected value, found module `a` - --> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5 + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:42:5 | LL | a.b.f(); - | ^-- - | | - | help: use the path separator to refer to an item: `a::b` + | ^- help: use the path separator to refer to an item: `::` error[E0423]: expected value, found module `a::b` - --> $DIR/suggest-path-instead-of-mod-dot-item.rs:40:12 + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:46:12 | LL | pub const I: i32 = 1; | --------------------- similarly named constant `I` defined here @@ -60,7 +52,7 @@ LL | v.push(a::b); | help: a constant with a similar name exists: `I` error[E0423]: expected value, found module `a::b` - --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5 + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:52:5 | LL | pub const I: i32 = 1; | --------------------- similarly named constant `I` defined here @@ -71,14 +63,14 @@ LL | a::b.f() help: use the path separator to refer to an item | LL | a::b::f() - | ~~~~~~~ + | ~~ help: a constant with a similar name exists | LL | a::I.f() | ~ error[E0423]: expected value, found module `a::b` - --> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5 + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:59:5 | LL | pub const I: i32 = 1; | --------------------- similarly named constant `I` defined here @@ -89,7 +81,7 @@ LL | a::b | help: a constant with a similar name exists: `I` error[E0423]: expected function, found module `a::b` - --> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:5 + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:65:5 | LL | pub const I: i32 = 1; | --------------------- similarly named constant `I` defined here @@ -99,6 +91,50 @@ LL | a::b() | | | help: a constant with a similar name exists: `I` -error: aborting due to 9 previous errors +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9 + | +LL | a + | ^ not a value +... +LL | module!().g::<()>(); // no `help` here! + | --------- in this macro invocation + | + = note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9 + | +LL | a + | ^ not a value +... +LL | module!().g; // no `help` here! + | --------- in this macro invocation + | + = note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:80:9 + | +LL | a.f() + | ^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(method); + | --------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:85:9 + | +LL | a.f + | ^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(field); + | -------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/suggestions/assoc-const-as-field.stderr b/src/test/ui/suggestions/assoc-const-as-field.stderr index 5e746ecb2f28f..78e5634b2de2a 100644 --- a/src/test/ui/suggestions/assoc-const-as-field.stderr +++ b/src/test/ui/suggestions/assoc-const-as-field.stderr @@ -2,9 +2,7 @@ error[E0423]: expected value, found struct `Mod::Foo` --> $DIR/assoc-const-as-field.rs:11:9 | LL | foo(Mod::Foo.Bar); - | ^^^^^^^^---- - | | - | help: use the path separator to refer to an item: `Mod::Foo::Bar` + | ^^^^^^^^- help: use the path separator to refer to an item: `::` error: aborting due to previous error From 48c0341a7081bb74bb4635529a94298b9be4b459 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Fri, 12 Aug 2022 18:11:01 +0900 Subject: [PATCH 03/14] suggest removing a semicolon after impl/trait items --- compiler/rustc_parse/src/parser/item.rs | 38 +++++++++++++++++-- ...ing-semicolon-after-impl-trait-items.fixed | 7 ++++ ...moving-semicolon-after-impl-trait-items.rs | 7 ++++ ...ng-semicolon-after-impl-trait-items.stderr | 18 +++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed create mode 100644 src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs create mode 100644 src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 72c23776d3399..8f4edf6ce4800 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -670,14 +670,44 @@ impl<'a> Parser<'a> { } match parse_item(self) { Ok(None) => { + let is_unnecessary_semicolon = !items.is_empty() + // When the close delim is `)` in a case like the following, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`, + // but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`. + // This is because the `token.kind` of the close delim is treated as the same as + // that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different. + // Therefore, `token.kind` should not be compared here. + // + // issue-60075.rs + // ``` + // trait T { + // fn qux() -> Option { + // let _ = if true { + // }); + // ^ this close delim + // Some(4) + // } + // ``` + && self + .span_to_snippet(self.prev_token.span) + .map_or(false, |snippet| snippet == "}") + && self.token.kind == token::Semi; + let semicolon_span = self.token.span; // We have to bail or we'll potentially never make progress. let non_item_span = self.token.span; self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes); - self.struct_span_err(non_item_span, "non-item in item list") - .span_label(open_brace_span, "item list starts here") + let mut err = self.struct_span_err(non_item_span, "non-item in item list"); + err.span_label(open_brace_span, "item list starts here") .span_label(non_item_span, "non-item starts here") - .span_label(self.prev_token.span, "item list ends here") - .emit(); + .span_label(self.prev_token.span, "item list ends here"); + if is_unnecessary_semicolon { + err.span_suggestion_verbose( + semicolon_span, + "consider removing this semicolon", + "", + Applicability::MaybeIncorrect, + ); + } + err.emit(); break; } Ok(Some(item)) => items.extend(item), diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed new file mode 100644 index 0000000000000..63704735490fa --- /dev/null +++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed @@ -0,0 +1,7 @@ +// run-rustfix + +trait Foo { + fn bar() {} //~ ERROR non-item in item list +} + +fn main() {} diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs new file mode 100644 index 0000000000000..4650b05e20ce8 --- /dev/null +++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs @@ -0,0 +1,7 @@ +// run-rustfix + +trait Foo { + fn bar() {}; //~ ERROR non-item in item list +} + +fn main() {} diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr new file mode 100644 index 0000000000000..bc12bfc02208c --- /dev/null +++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr @@ -0,0 +1,18 @@ +error: non-item in item list + --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:4:16 + | +LL | trait Foo { + | - item list starts here +LL | fn bar() {}; + | ^ non-item starts here +LL | } + | - item list ends here + | +help: consider removing this semicolon + | +LL - fn bar() {}; +LL + fn bar() {} + | + +error: aborting due to previous error + From b821ce6097812763fd6136a90b42f90a71364e76 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 11 Aug 2022 22:20:35 +0000 Subject: [PATCH 04/14] enum variant ctor inherits stability of variant --- compiler/rustc_passes/src/stability.rs | 2 +- .../ui/stability-attribute/auxiliary/ctor-stability.rs | 8 ++++++++ src/test/ui/stability-attribute/ctor-stability.rs | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/stability-attribute/auxiliary/ctor-stability.rs create mode 100644 src/test/ui/stability-attribute/ctor-stability.rs diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 574e8073d8efd..3ec270a7c97f6 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -460,7 +460,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, - InheritStability::No, + InheritStability::Yes, |_| {}, ); } diff --git a/src/test/ui/stability-attribute/auxiliary/ctor-stability.rs b/src/test/ui/stability-attribute/auxiliary/ctor-stability.rs new file mode 100644 index 0000000000000..74c6023d7fbbd --- /dev/null +++ b/src/test/ui/stability-attribute/auxiliary/ctor-stability.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] +#![feature(staged_api)] +#![stable(feature = "none", since = "1.0")] + +#[stable(feature = "none", since = "1.0")] +pub enum Foo { + A, +} diff --git a/src/test/ui/stability-attribute/ctor-stability.rs b/src/test/ui/stability-attribute/ctor-stability.rs new file mode 100644 index 0000000000000..fcab0cb109940 --- /dev/null +++ b/src/test/ui/stability-attribute/ctor-stability.rs @@ -0,0 +1,8 @@ +// aux-build:ctor-stability.rs +// check-pass + +extern crate ctor_stability; + +fn main() { + let _ = ctor_stability::Foo::A; +} From 6925f4101b426c66abe20e8acdddf8c20fd1e87c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 11 Aug 2022 22:25:16 +0000 Subject: [PATCH 05/14] Check ctor for missing stability --- compiler/rustc_passes/src/stability.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 3ec270a7c97f6..972999deb18f1 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -600,6 +600,9 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) { self.check_missing_stability(self.tcx.hir().local_def_id(var.id), var.span); + if let Some(ctor_hir_id) = var.data.ctor_hir_id() { + self.check_missing_stability(self.tcx.hir().local_def_id(ctor_hir_id), var.span); + } intravisit::walk_variant(self, var); } From 20121fa781e89893ad658cb333a226b81c5543b2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Jul 2022 17:17:19 +0000 Subject: [PATCH 06/14] Point out a single arg if we have a single arg incompatibility --- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 45 +++++++++++-------- .../invalid_arguments.stderr | 20 ++++----- src/test/ui/argument-suggestions/too-long.rs | 41 +++++++++++++++++ .../ui/argument-suggestions/too-long.stderr | 24 ++++++++++ ...ted-type-projection-from-supertrait.stderr | 8 ++-- .../associated-types-path-2.stderr | 2 +- src/test/ui/async-await/generator-desc.stderr | 4 +- .../coerce-reborrow-multi-arg-fail.stderr | 2 +- src/test/ui/coercion/coerce-to-bang.stderr | 10 ++--- src/test/ui/fn/fn-item-type.stderr | 10 ++--- src/test/ui/issues/issue-11374.stderr | 2 +- .../ui/methods/method-call-err-msg.stderr | 8 ++-- src/test/ui/span/issue-34264.stderr | 2 +- src/test/ui/span/missing-unit-argument.stderr | 4 +- src/test/ui/traits/multidispatch-bad.stderr | 2 +- .../tuple/add-tuple-within-arguments.stderr | 4 +- 16 files changed, 130 insertions(+), 58 deletions(-) create mode 100644 src/test/ui/argument-suggestions/too-long.rs create mode 100644 src/test/ui/argument-suggestions/too-long.stderr diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 1d1f755947fdc..afd22094e500c 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -440,7 +440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &hir::Expr<'tcx>, ) { // Next, let's construct the error - let (error_span, full_call_span, ctor_of) = match &call_expr.kind { + let (error_span, full_call_span, ctor_of, is_method) = match &call_expr.kind { hir::ExprKind::Call( hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. }, _, @@ -448,12 +448,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Res::Def(DefKind::Ctor(of, _), _) = self.typeck_results.borrow().qpath_res(qpath, *hir_id) { - (call_span, *span, Some(of)) + (call_span, *span, Some(of), false) } else { - (call_span, *span, None) + (call_span, *span, None, false) } } - hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None), + hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None, false), hir::ExprKind::MethodCall(path_segment, _, span) => { let ident_span = path_segment.ident.span; let ident_span = if let Some(args) = path_segment.args { @@ -461,9 +461,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { ident_span }; - ( - *span, ident_span, None, // methods are never ctors - ) + // methods are never ctors + (*span, ident_span, None, true) } k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k), }; @@ -659,7 +658,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); }; - self.label_fn_like(&mut err, fn_def_id, callee_ty); + self.label_fn_like(&mut err, fn_def_id, callee_ty, Some(mismatch_idx), is_method); err.emit(); return; } @@ -701,16 +700,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } errors.drain_filter(|error| { - let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(error)) = error else { return false }; + let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false }; let (provided_ty, provided_span) = provided_arg_tys[*provided_idx]; let (expected_ty, _) = formal_and_expected_inputs[*expected_idx]; let cause = &self.misc(provided_span); let trace = TypeTrace::types(cause, true, expected_ty, provided_ty); - if let Some(e) = error { - if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) { - self.report_and_explain_type_error(trace, e).emit(); - return true; - } + if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) { + self.report_and_explain_type_error(trace, e).emit(); + return true; } false }); @@ -749,7 +746,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("arguments to this {} are incorrect", call_name), ); // Call out where the function is defined - self.label_fn_like(&mut err, fn_def_id, callee_ty); + self.label_fn_like(&mut err, fn_def_id, callee_ty, Some(expected_idx.as_usize()), is_method); err.emit(); return; } @@ -1031,7 +1028,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Call out where the function is defined - self.label_fn_like(&mut err, fn_def_id, callee_ty); + self.label_fn_like(&mut err, fn_def_id, callee_ty, None, is_method); // And add a suggestion block for all of the parameters let suggestion_text = match suggestion_text { @@ -1781,6 +1778,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err: &mut Diagnostic, callable_def_id: Option, callee_ty: Option>, + // A specific argument should be labeled, instead of all of them + expected_idx: Option, + is_method: bool, ) { let Some(mut def_id) = callable_def_id else { return; @@ -1881,10 +1881,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .get_if_local(def_id) .and_then(|node| node.body_id()) .into_iter() - .flat_map(|id| self.tcx.hir().body(id).params); + .flat_map(|id| self.tcx.hir().body(id).params) + .skip(if is_method { 1 } else { 0 }); - for param in params { - spans.push_span_label(param.span, ""); + for (idx, param) in params.into_iter().enumerate() { + if let Some(expected_idx) = expected_idx { + if idx == expected_idx { + spans.push_span_label(param.span, ""); + } + } else { + spans.push_span_label(param.span, ""); + } } let def_kind = self.tcx.def_kind(def_id); diff --git a/src/test/ui/argument-suggestions/invalid_arguments.stderr b/src/test/ui/argument-suggestions/invalid_arguments.stderr index 33f27d48fec80..303f086957853 100644 --- a/src/test/ui/argument-suggestions/invalid_arguments.stderr +++ b/src/test/ui/argument-suggestions/invalid_arguments.stderr @@ -24,7 +24,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:6:4 | LL | fn two_arg_same(_a: i32, _b: i32) {} - | ^^^^^^^^^^^^ ------- ------- + | ^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:17:16 @@ -38,7 +38,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:6:4 | LL | fn two_arg_same(_a: i32, _b: i32) {} - | ^^^^^^^^^^^^ ------- ------- + | ^^^^^^^^^^^^ ------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:18:3 @@ -66,7 +66,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:7:4 | LL | fn two_arg_diff(_a: i32, _b: f32) {} - | ^^^^^^^^^^^^ ------- ------- + | ^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:20:16 @@ -80,7 +80,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:7:4 | LL | fn two_arg_diff(_a: i32, _b: f32) {} - | ^^^^^^^^^^^^ ------- ------- + | ^^^^^^^^^^^^ ------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:21:3 @@ -108,7 +108,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:8:4 | LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} - | ^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:25:21 @@ -122,7 +122,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:8:4 | LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} - | ^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:26:26 @@ -136,7 +136,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:8:4 | LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} - | ^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^ -------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:28:3 @@ -207,7 +207,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:9:4 | LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} - | ^^^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:35:23 @@ -221,7 +221,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:9:4 | LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} - | ^^^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:36:26 @@ -235,7 +235,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:9:4 | LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} - | ^^^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^^^ -------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:38:3 diff --git a/src/test/ui/argument-suggestions/too-long.rs b/src/test/ui/argument-suggestions/too-long.rs new file mode 100644 index 0000000000000..7ec56afae1ce9 --- /dev/null +++ b/src/test/ui/argument-suggestions/too-long.rs @@ -0,0 +1,41 @@ +struct Qux; + +impl Qux { + fn foo( + &self, + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, + l: i32, + ) { + } +} + +fn what( + qux: &Qux, + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: &i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, + l: i32, +) { + qux.foo(a, b, c, d, e, f, g, h, i, j, k, l); + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/argument-suggestions/too-long.stderr b/src/test/ui/argument-suggestions/too-long.stderr new file mode 100644 index 0000000000000..bd430194c5edf --- /dev/null +++ b/src/test/ui/argument-suggestions/too-long.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/too-long.rs:37:28 + | +LL | qux.foo(a, b, c, d, e, f, g, h, i, j, k, l); + | --- ^ expected `i32`, found `&i32` + | | + | arguments to this function are incorrect + | +note: associated function defined here + --> $DIR/too-long.rs:4:8 + | +LL | fn foo( + | ^^^ +... +LL | f: i32, + | ------ +help: consider dereferencing the borrow + | +LL | qux.foo(a, b, c, d, e, *f, g, h, i, j, k, l); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr b/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr index b904ad102e97e..e761c6c62a6cf 100644 --- a/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr +++ b/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr @@ -10,7 +10,7 @@ note: function defined here --> $DIR/associated-type-projection-from-supertrait.rs:25:4 | LL | fn dent(c: C, color: C::Color) { c.chip_paint(color) } - | ^^^^ ---- --------------- + | ^^^^ --------------- error[E0308]: mismatched types --> $DIR/associated-type-projection-from-supertrait.rs:28:23 @@ -24,7 +24,7 @@ note: function defined here --> $DIR/associated-type-projection-from-supertrait.rs:25:4 | LL | fn dent(c: C, color: C::Color) { c.chip_paint(color) } - | ^^^^ ---- --------------- + | ^^^^ --------------- error[E0308]: mismatched types --> $DIR/associated-type-projection-from-supertrait.rs:32:28 @@ -38,7 +38,7 @@ note: associated function defined here --> $DIR/associated-type-projection-from-supertrait.rs:12:8 | LL | fn chip_paint(&self, c: Self::Color) { } - | ^^^^^^^^^^ ----- -------------- + | ^^^^^^^^^^ -------------- error[E0308]: mismatched types --> $DIR/associated-type-projection-from-supertrait.rs:33:28 @@ -52,7 +52,7 @@ note: associated function defined here --> $DIR/associated-type-projection-from-supertrait.rs:12:8 | LL | fn chip_paint(&self, c: Self::Color) { } - | ^^^^^^^^^^ ----- -------------- + | ^^^^^^^^^^ -------------- error: aborting due to 4 previous errors diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr index 1d0b84d31d410..c37d469890c08 100644 --- a/src/test/ui/associated-types/associated-types-path-2.stderr +++ b/src/test/ui/associated-types/associated-types-path-2.stderr @@ -10,7 +10,7 @@ note: function defined here --> $DIR/associated-types-path-2.rs:13:8 | LL | pub fn f1(a: T, x: T::A) {} - | ^^ ---- ------- + | ^^ ------- help: change the type of the numeric literal from `i32` to `u32` | LL | f1(2i32, 4u32); diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr index 3be8c552063e7..2494c3feb2a89 100644 --- a/src/test/ui/async-await/generator-desc.stderr +++ b/src/test/ui/async-await/generator-desc.stderr @@ -42,7 +42,7 @@ note: function defined here --> $DIR/generator-desc.rs:8:4 | LL | fn fun>(f1: F, f2: F) {} - | ^^^ ----- ----- + | ^^^ ----- error[E0308]: mismatched types --> $DIR/generator-desc.rs:14:26 @@ -67,7 +67,7 @@ note: function defined here --> $DIR/generator-desc.rs:8:4 | LL | fn fun>(f1: F, f2: F) {} - | ^^^ ----- ----- + | ^^^ ----- error: aborting due to 3 previous errors diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr index 36551e5afc6c6..5cbdef2183114 100644 --- a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr +++ b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr @@ -12,7 +12,7 @@ note: function defined here --> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4 | LL | fn test(_a: T, _b: T) {} - | ^^^^ ----- ----- + | ^^^^ ----- error: aborting due to previous error diff --git a/src/test/ui/coercion/coerce-to-bang.stderr b/src/test/ui/coercion/coerce-to-bang.stderr index add8f14cfa591..1207dc7e7a2ff 100644 --- a/src/test/ui/coercion/coerce-to-bang.stderr +++ b/src/test/ui/coercion/coerce-to-bang.stderr @@ -12,7 +12,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:18:13 @@ -28,7 +28,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:26:12 @@ -44,7 +44,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:36:12 @@ -60,7 +60,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:45:12 @@ -76,7 +76,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:50:21 diff --git a/src/test/ui/fn/fn-item-type.stderr b/src/test/ui/fn/fn-item-type.stderr index ecc6485d6d2b5..f03a47d5c2c75 100644 --- a/src/test/ui/fn/fn-item-type.stderr +++ b/src/test/ui/fn/fn-item-type.stderr @@ -15,7 +15,7 @@ note: function defined here --> $DIR/fn-item-type.rs:7:4 | LL | fn eq(x: T, y: T) { } - | ^^ ---- ---- + | ^^ ---- error[E0308]: mismatched types --> $DIR/fn-item-type.rs:22:19 @@ -34,7 +34,7 @@ note: function defined here --> $DIR/fn-item-type.rs:7:4 | LL | fn eq(x: T, y: T) { } - | ^^ ---- ---- + | ^^ ---- error[E0308]: mismatched types --> $DIR/fn-item-type.rs:29:23 @@ -53,7 +53,7 @@ note: function defined here --> $DIR/fn-item-type.rs:7:4 | LL | fn eq(x: T, y: T) { } - | ^^ ---- ---- + | ^^ ---- error[E0308]: mismatched types --> $DIR/fn-item-type.rs:38:26 @@ -72,7 +72,7 @@ note: function defined here --> $DIR/fn-item-type.rs:7:4 | LL | fn eq(x: T, y: T) { } - | ^^ ---- ---- + | ^^ ---- error[E0308]: mismatched types --> $DIR/fn-item-type.rs:45:19 @@ -90,7 +90,7 @@ note: function defined here --> $DIR/fn-item-type.rs:7:4 | LL | fn eq(x: T, y: T) { } - | ^^ ---- ---- + | ^^ ---- error: aborting due to 5 previous errors diff --git a/src/test/ui/issues/issue-11374.stderr b/src/test/ui/issues/issue-11374.stderr index 3a1d43310e2fc..15b2bbeb7c295 100644 --- a/src/test/ui/issues/issue-11374.stderr +++ b/src/test/ui/issues/issue-11374.stderr @@ -14,7 +14,7 @@ note: associated function defined here --> $DIR/issue-11374.rs:13:12 | LL | pub fn read_to(&mut self, vec: &mut [u8]) { - | ^^^^^^^ --------- -------------- + | ^^^^^^^ -------------- error: aborting due to previous error diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 690fe8fa7af10..e9b49c89bf162 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -8,7 +8,7 @@ note: associated function defined here --> $DIR/method-call-err-msg.rs:5:8 | LL | fn zero(self) -> Foo { self } - | ^^^^ ---- + | ^^^^ help: remove the extra argument | LL | x.zero() @@ -24,7 +24,7 @@ note: associated function defined here --> $DIR/method-call-err-msg.rs:6:8 | LL | fn one(self, _: isize) -> Foo { self } - | ^^^ ---- -------- + | ^^^ -------- help: provide the argument | LL | .one(/* isize */) @@ -40,7 +40,7 @@ note: associated function defined here --> $DIR/method-call-err-msg.rs:7:8 | LL | fn two(self, _: isize, _: isize) -> Foo { self } - | ^^^ ---- -------- -------- + | ^^^ -------- -------- help: provide the argument | LL | .two(0, /* isize */); @@ -80,7 +80,7 @@ note: associated function defined here --> $DIR/method-call-err-msg.rs:8:8 | LL | fn three(self, _: T, _: T, _: T) -> Foo { self } - | ^^^^^ ---- ---- ---- ---- + | ^^^^^ ---- ---- ---- help: provide the arguments | LL | y.three::(/* usize */, /* usize */, /* usize */); diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index e676d7372e891..28a911d0c5bfa 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -78,7 +78,7 @@ note: function defined here --> $DIR/issue-34264.rs:3:4 | LL | fn bar(x, y: usize) {} - | ^^^ - -------- + | ^^^ -------- error[E0061]: this function takes 2 arguments but 3 arguments were supplied --> $DIR/issue-34264.rs:10:5 diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr index e68260e4a0940..d2afd277ecf79 100644 --- a/src/test/ui/span/missing-unit-argument.stderr +++ b/src/test/ui/span/missing-unit-argument.stderr @@ -72,7 +72,7 @@ note: associated function defined here --> $DIR/missing-unit-argument.rs:6:8 | LL | fn baz(self, (): ()) { } - | ^^^ ---- ------ + | ^^^ ------ help: provide the argument | LL | S.baz(()); @@ -88,7 +88,7 @@ note: associated function defined here --> $DIR/missing-unit-argument.rs:7:8 | LL | fn generic(self, _: T) { } - | ^^^^^^^ ---- ---- + | ^^^^^^^ ---- help: provide the argument | LL | S.generic::<()>(()); diff --git a/src/test/ui/traits/multidispatch-bad.stderr b/src/test/ui/traits/multidispatch-bad.stderr index 8b6e610067be1..d58f1e2d9e59c 100644 --- a/src/test/ui/traits/multidispatch-bad.stderr +++ b/src/test/ui/traits/multidispatch-bad.stderr @@ -10,7 +10,7 @@ note: function defined here --> $DIR/multidispatch-bad.rs:13:4 | LL | fn test(_: T, _: U) - | ^^^^ ---- ---- + | ^^^^ ---- help: change the type of the numeric literal from `i32` to `u32` | LL | test(22i32, 44u32); diff --git a/src/test/ui/tuple/add-tuple-within-arguments.stderr b/src/test/ui/tuple/add-tuple-within-arguments.stderr index 95df96ca0dd4f..7029d298d71e2 100644 --- a/src/test/ui/tuple/add-tuple-within-arguments.stderr +++ b/src/test/ui/tuple/add-tuple-within-arguments.stderr @@ -8,7 +8,7 @@ note: function defined here --> $DIR/add-tuple-within-arguments.rs:1:4 | LL | fn foo(s: &str, a: (i32, i32), s2: &str) {} - | ^^^ ------- ------------- -------- + | ^^^ ------------- help: wrap these arguments in parentheses to construct a tuple | LL | foo("hi", (1, 2), "hi"); @@ -28,7 +28,7 @@ note: function defined here --> $DIR/add-tuple-within-arguments.rs:3:4 | LL | fn bar(s: &str, a: (&str,), s2: &str) {} - | ^^^ ------- ---------- -------- + | ^^^ ---------- help: use a trailing comma to create a tuple with one element | LL | bar("hi", ("hi",), "hi"); From 262644d94a8391acc6cb806b62b8de6bc02123f5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Jul 2022 17:43:21 +0000 Subject: [PATCH 07/14] And for closures --- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 19 ++++++++++++++++++- .../unboxed-closures-type-mismatch.stderr | 6 +++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index afd22094e500c..0027792442d02 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -746,7 +746,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("arguments to this {} are incorrect", call_name), ); // Call out where the function is defined - self.label_fn_like(&mut err, fn_def_id, callee_ty, Some(expected_idx.as_usize()), is_method); + self.label_fn_like( + &mut err, + fn_def_id, + callee_ty, + Some(expected_idx.as_usize()), + is_method, + ); err.emit(); return; } @@ -1896,6 +1902,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let def_kind = self.tcx.def_kind(def_id); err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id))); + } else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id) + && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind + { + let param = expected_idx + .and_then(|expected_idx| self.tcx.hir().body(*body).params.get(expected_idx)); + let (kind, span) = if let Some(param) = param { + ("closure parameter", param.span) + } else { + ("closure", self.tcx.def_span(def_id)) + }; + err.span_note(span, &format!("{} defined here", kind)); } else { let def_kind = self.tcx.def_kind(def_id); err.span_note( diff --git a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr index 3241c9f8521c0..c7d7d7d5f25d2 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr @@ -6,11 +6,11 @@ LL | let z = f(1_usize, 2); | | | arguments to this function are incorrect | -note: closure defined here - --> $DIR/unboxed-closures-type-mismatch.rs:4:17 +note: closure parameter defined here + --> $DIR/unboxed-closures-type-mismatch.rs:4:18 | LL | let mut f = |x: isize, y: isize| -> isize { x + y }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ help: change the type of the numeric literal from `usize` to `isize` | LL | let z = f(1_isize, 2); From 237cbe91a83905abe379586f10605999c1e0bc4d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Jul 2022 17:46:20 +0000 Subject: [PATCH 08/14] Adjust span of closure param --- compiler/rustc_parse/src/parser/expr.rs | 2 +- .../ui/unboxed-closures/unboxed-closures-type-mismatch.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 2880ef78c8d27..33bebfc2c9ab5 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2268,7 +2268,7 @@ impl<'a> Parser<'a> { attrs: attrs.into(), ty, pat, - span: lo.to(this.token.span), + span: lo.to(this.prev_token.span), id: DUMMY_NODE_ID, is_placeholder: false, }, diff --git a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr index c7d7d7d5f25d2..455f83f5721bd 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr @@ -10,7 +10,7 @@ note: closure parameter defined here --> $DIR/unboxed-closures-type-mismatch.rs:4:18 | LL | let mut f = |x: isize, y: isize| -> isize { x + y }; - | ^^^^^^^^^ + | ^^^^^^^^ help: change the type of the numeric literal from `usize` to `isize` | LL | let z = f(1_isize, 2); From c6089189b3045648a8b37ee65dfc2e7e139789b0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Aug 2022 15:35:27 +0000 Subject: [PATCH 09/14] Address nit --- compiler/rustc_typeck/src/check/fn_ctxt/checks.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 0027792442d02..5d668fdaf80c7 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -1890,14 +1890,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .flat_map(|id| self.tcx.hir().body(id).params) .skip(if is_method { 1 } else { 0 }); - for (idx, param) in params.into_iter().enumerate() { - if let Some(expected_idx) = expected_idx { - if idx == expected_idx { - spans.push_span_label(param.span, ""); - } - } else { - spans.push_span_label(param.span, ""); - } + for (_, param) in params + .into_iter() + .enumerate() + .filter(|(idx, _)| expected_idx.map_or(true, |expected_idx| expected_idx == *idx)) + { + spans.push_span_label(param.span, ""); } let def_kind = self.tcx.def_kind(def_id); From de8dedb0a524208e4856e80c22bc7f47df2fd91a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 12 Aug 2022 15:39:26 -0700 Subject: [PATCH 10/14] Use an extensionless `x` script for non-Windows --- src/bootstrap/mk/Makefile.in | 2 +- src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile | 4 ++-- src/tools/tidy/src/bins.rs | 2 +- x.sh => x | 0 x.ps1 | 2 +- x.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename x.sh => x (100%) diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 1e0f7e9acf4f2..9a08a7be0f5f7 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -80,7 +80,7 @@ TESTS_IN_MINGW_2 := \ src/test/ui ci-mingw-subset-1: - $(Q)$(CFG_SRC_DIR)/x.sh test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %) + $(Q)$(CFG_SRC_DIR)/x test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %) ci-mingw-subset-2: $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile index 8de9045c3baa7..14d0ffd75005f 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile @@ -44,7 +44,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-llvm-link-shared \ --set rust.thin-lto-import-instr-limit=10 -# NOTE: intentionally uses all of `x.py`, `x.sh`, and `x.ps1` to make sure they all work on Linux. +# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux. ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \ # Run the `mir-opt` tests again but this time for a 32-bit target. # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have @@ -52,7 +52,7 @@ ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \ # the PR is approved and tested for merging. # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`, # despite having different output on 32-bit vs 64-bit targets. - ../x.sh --stage 2 test src/test/mir-opt \ + ../x --stage 2 test src/test/mir-opt \ --host='' --target=i686-unknown-linux-gnu && \ # Run the UI test suite again, but in `--pass=check` mode # diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 025b8ab9f0af5..30903f56d93b0 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -98,7 +98,7 @@ mod os_impl { pub fn check(path: &Path, bad: &mut bool) { use std::ffi::OsStr; - const ALLOWED: &[&str] = &["configure"]; + const ALLOWED: &[&str] = &["configure", "x"]; crate::walk_no_read( path, diff --git a/x.sh b/x similarity index 100% rename from x.sh rename to x diff --git a/x.ps1 b/x.ps1 index 1225443735f7b..86cea606591ba 100755 --- a/x.ps1 +++ b/x.ps1 @@ -1,6 +1,6 @@ #!/usr/bin/env pwsh -# See x.sh for why these scripts exist. +# See ./x for why these scripts exist. $xpy = Join-Path $PSScriptRoot x.py # Start-Process for some reason splits arguments on spaces. (Isn't powershell supposed to be simpler than bash?) diff --git a/x.py b/x.py index 6c68907c58145..6df4033d55d72 100755 --- a/x.py +++ b/x.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # Some systems don't have `python3` in their PATH. This isn't supported by x.py directly; -# they should use `x.sh` or `x.ps1` instead. +# they should use `x` or `x.ps1` instead. # This file is only a "symlink" to bootstrap.py, all logic should go there. From d47df26784355eaa4006eee60f262c6035fea307 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 13 Aug 2022 22:10:54 +0900 Subject: [PATCH 11/14] use `span_suggestion` instead of `span_suggestion_verbose` --- compiler/rustc_parse/src/parser/item.rs | 2 +- ...t-removing-semicolon-after-impl-trait-items.stderr | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 8f4edf6ce4800..8f58bce889041 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -700,7 +700,7 @@ impl<'a> Parser<'a> { .span_label(non_item_span, "non-item starts here") .span_label(self.prev_token.span, "item list ends here"); if is_unnecessary_semicolon { - err.span_suggestion_verbose( + err.span_suggestion( semicolon_span, "consider removing this semicolon", "", diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr index bc12bfc02208c..396e0c130f11b 100644 --- a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr +++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr @@ -4,15 +4,12 @@ error: non-item in item list LL | trait Foo { | - item list starts here LL | fn bar() {}; - | ^ non-item starts here + | ^ + | | + | non-item starts here + | help: consider removing this semicolon LL | } | - item list ends here - | -help: consider removing this semicolon - | -LL - fn bar() {}; -LL + fn bar() {} - | error: aborting due to previous error From b0cd1e192c2e217c08f2759d86a3807acb8e2178 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Aug 2022 05:22:47 +0000 Subject: [PATCH 12/14] Label argument coercion errors --- compiler/rustc_typeck/src/check/fn_ctxt/checks.rs | 4 +++- src/test/ui/argument-suggestions/issue-96638.stderr | 4 +++- src/test/ui/argument-suggestions/issue-97484.stderr | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 1d1f755947fdc..11f11d8c61226 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -545,7 +545,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); let can_coerce = self.can_coerce(arg_ty, coerced_ty); if !can_coerce { - return Compatibility::Incompatible(None); + return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts( + ty::error::ExpectedFound::new(true, coerced_ty, arg_ty), + ))); } // Using probe here, since we don't want this subtyping to affect inference. diff --git a/src/test/ui/argument-suggestions/issue-96638.stderr b/src/test/ui/argument-suggestions/issue-96638.stderr index 8af31b8b751f3..804cb1aa32219 100644 --- a/src/test/ui/argument-suggestions/issue-96638.stderr +++ b/src/test/ui/argument-suggestions/issue-96638.stderr @@ -2,7 +2,9 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied --> $DIR/issue-96638.rs:8:5 | LL | f(&x, ""); - | ^ -- an argument of type `usize` is missing + | ^ -- -- expected `usize`, found `&str` + | | + | an argument of type `usize` is missing | note: function defined here --> $DIR/issue-96638.rs:1:4 diff --git a/src/test/ui/argument-suggestions/issue-97484.stderr b/src/test/ui/argument-suggestions/issue-97484.stderr index 9589e919c0a1f..b5dedf0f4fa05 100644 --- a/src/test/ui/argument-suggestions/issue-97484.stderr +++ b/src/test/ui/argument-suggestions/issue-97484.stderr @@ -2,8 +2,9 @@ error[E0061]: this function takes 4 arguments but 7 arguments were supplied --> $DIR/issue-97484.rs:12:5 | LL | foo(&&A, B, C, D, E, F, G); - | ^^^ - - - argument of type `F` unexpected - | | | + | ^^^ - - - - argument of type `F` unexpected + | | | | + | | | expected `&E`, found struct `E` | | argument of type `C` unexpected | argument of type `B` unexpected | From aa1a07f114740ef067a5a586fbe5d4f763788460 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Aug 2022 05:44:20 +0000 Subject: [PATCH 13/14] Do not inline non-simple argument type errors into labels --- .../src/infer/error_reporting/mod.rs | 6 ++-- .../two-mismatch-notes.rs | 11 +++++++ .../two-mismatch-notes.stderr | 29 +++++++++++++++++++ src/test/ui/issues/issue-18819.stderr | 10 ++++--- .../args-instead-of-tuple-errors.stderr | 18 ++++++++---- src/test/ui/tuple/wrong_argument_ice-3.stderr | 9 ++++-- 6 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/argument-suggestions/two-mismatch-notes.rs create mode 100644 src/test/ui/argument-suggestions/two-mismatch-notes.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 20864c657ffd7..772b81992c46b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1424,7 +1424,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// E0271, like `src/test/ui/issues/issue-39970.stderr`. #[tracing::instrument( level = "debug", - skip(self, diag, secondary_span, swap_secondary_and_primary, force_label) + skip(self, diag, secondary_span, swap_secondary_and_primary, prefer_label) )] pub fn note_type_err( &self, @@ -1434,7 +1434,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { mut values: Option>, terr: &TypeError<'tcx>, swap_secondary_and_primary: bool, - force_label: bool, + prefer_label: bool, ) { let span = cause.span(); @@ -1612,7 +1612,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { TypeError::ObjectUnsafeCoercion(_) => {} _ => { let mut label_or_note = |span: Span, msg: &str| { - if force_label || &[span] == diag.span.primary_spans() { + if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() { diag.span_label(span, msg); } else { diag.span_note(span, msg); diff --git a/src/test/ui/argument-suggestions/two-mismatch-notes.rs b/src/test/ui/argument-suggestions/two-mismatch-notes.rs new file mode 100644 index 0000000000000..1309041ab9a59 --- /dev/null +++ b/src/test/ui/argument-suggestions/two-mismatch-notes.rs @@ -0,0 +1,11 @@ +#[derive(Copy, Clone)] +struct Wrapper(T); + +fn foo(_: fn(i32), _: Wrapper) {} + +fn f(_: u32) {} + +fn main() { + let w = Wrapper::(1isize); + foo(f, w); //~ ERROR arguments to this function are incorrect +} diff --git a/src/test/ui/argument-suggestions/two-mismatch-notes.stderr b/src/test/ui/argument-suggestions/two-mismatch-notes.stderr new file mode 100644 index 0000000000000..7873cf964cbbc --- /dev/null +++ b/src/test/ui/argument-suggestions/two-mismatch-notes.stderr @@ -0,0 +1,29 @@ +error[E0308]: arguments to this function are incorrect + --> $DIR/two-mismatch-notes.rs:10:5 + | +LL | foo(f, w); + | ^^^ + | +note: expected `i32`, found `u32` + --> $DIR/two-mismatch-notes.rs:10:9 + | +LL | foo(f, w); + | ^ + = note: expected fn pointer `fn(i32)` + found fn item `fn(u32) {f}` +note: expected `i32`, found `isize` + --> $DIR/two-mismatch-notes.rs:10:12 + | +LL | foo(f, w); + | ^ + = note: expected struct `Wrapper` + found struct `Wrapper` +note: function defined here + --> $DIR/two-mismatch-notes.rs:4:4 + | +LL | fn foo(_: fn(i32), _: Wrapper) {} + | ^^^ ---------- --------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-18819.stderr b/src/test/ui/issues/issue-18819.stderr index 6499dd0d81b1c..e499d0572f607 100644 --- a/src/test/ui/issues/issue-18819.stderr +++ b/src/test/ui/issues/issue-18819.stderr @@ -2,11 +2,13 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/issue-18819.rs:16:5 | LL | print_x(X); - | ^^^^^^^--- - | || - | |expected reference, found struct `X` - | an argument of type `&str` is missing + | ^^^^^^^--- an argument of type `&str` is missing | +note: expected reference, found struct `X` + --> $DIR/issue-18819.rs:16:13 + | +LL | print_x(X); + | ^ = note: expected reference `&dyn Foo` found struct `X` note: function defined here diff --git a/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr index 805c75f464cd5..4c952669cfafd 100644 --- a/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr +++ b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr @@ -2,10 +2,13 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied --> $DIR/args-instead-of-tuple-errors.rs:6:34 | LL | let _: Option<(i32, bool)> = Some(1, 2); - | ^^^^ - - argument of type `{integer}` unexpected - | | - | expected tuple, found integer + | ^^^^ - argument of type `{integer}` unexpected | +note: expected tuple, found integer + --> $DIR/args-instead-of-tuple-errors.rs:6:39 + | +LL | let _: Option<(i32, bool)> = Some(1, 2); + | ^ = note: expected tuple `(i32, bool)` found type `{integer}` note: tuple variant defined here @@ -22,10 +25,13 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/args-instead-of-tuple-errors.rs:8:5 | LL | int_bool(1, 2); - | ^^^^^^^^ - - argument of type `{integer}` unexpected - | | - | expected tuple, found integer + | ^^^^^^^^ - argument of type `{integer}` unexpected | +note: expected tuple, found integer + --> $DIR/args-instead-of-tuple-errors.rs:8:14 + | +LL | int_bool(1, 2); + | ^ = note: expected tuple `(i32, bool)` found type `{integer}` note: function defined here diff --git a/src/test/ui/tuple/wrong_argument_ice-3.stderr b/src/test/ui/tuple/wrong_argument_ice-3.stderr index 2733fb3149b55..968cb75db7633 100644 --- a/src/test/ui/tuple/wrong_argument_ice-3.stderr +++ b/src/test/ui/tuple/wrong_argument_ice-3.stderr @@ -2,10 +2,13 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/wrong_argument_ice-3.rs:9:16 | LL | groups.push(new_group, vec![process]); - | ^^^^ --------- ------------- argument of type `Vec<&Process>` unexpected - | | - | expected tuple, found struct `Vec` + | ^^^^ ------------- argument of type `Vec<&Process>` unexpected | +note: expected tuple, found struct `Vec` + --> $DIR/wrong_argument_ice-3.rs:9:21 + | +LL | groups.push(new_group, vec![process]); + | ^^^^^^^^^ = note: expected tuple `(Vec, Vec)` found struct `Vec` note: associated function defined here From 752b0e0672bf774847aac27f4c160248fefa6e40 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 9 Aug 2022 02:48:01 +0000 Subject: [PATCH 14/14] make clean::Item::span return option instead of dummy span --- src/librustdoc/clean/types.rs | 23 ++++++------------- src/librustdoc/html/render/context.rs | 5 +--- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/sources.rs | 2 ++ src/librustdoc/json/conversions.rs | 2 +- .../passes/calculate_doc_coverage.rs | 18 ++++++++------- src/test/rustdoc-json/impls/auto.rs | 18 +++++++++++++++ 7 files changed, 40 insertions(+), 30 deletions(-) create mode 100644 src/test/rustdoc-json/impls/auto.rs diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 91d5758077c94..1a4786c9b0664 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -415,29 +415,28 @@ impl Item { .unwrap_or(false) } - pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Span { + pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option { let kind = match &*self.kind { ItemKind::StrippedItem(k) => k, _ => &*self.kind, }; match kind { - ItemKind::ModuleItem(Module { span, .. }) => *span, - ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => Span::dummy(), + ItemKind::ModuleItem(Module { span, .. }) => Some(*span), + ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None, ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => { if let ItemId::Blanket { impl_id, .. } = self.item_id { - rustc_span(impl_id, tcx) + Some(rustc_span(impl_id, tcx)) } else { panic!("blanket impl item has non-blanket ID") } } - _ => { - self.item_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy) - } + _ => self.item_id.as_def_id().map(|did| rustc_span(did, tcx)), } } pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span { - crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner()) + crate::passes::span_of_attrs(&self.attrs) + .unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner())) } /// Finds the `doc` attribute as a NameValue and returns the corresponding @@ -2109,14 +2108,6 @@ impl Span { self.0 } - pub(crate) fn dummy() -> Self { - Self(rustc_span::DUMMY_SP) - } - - pub(crate) fn is_dummy(&self) -> bool { - self.0.is_dummy() - } - pub(crate) fn filename(&self, sess: &Session) -> FileName { sess.source_map().span_to_filename(self.0) } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 2ed7a6f1bb144..6f029c66c0b7d 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -301,13 +301,10 @@ impl<'tcx> Context<'tcx> { /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. pub(super) fn src_href(&self, item: &clean::Item) -> Option { - self.href_from_span(item.span(self.tcx()), true) + self.href_from_span(item.span(self.tcx())?, true) } pub(crate) fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option { - if span.is_dummy() { - return None; - } let mut root = self.root_path(); let mut path = String::new(); let cnum = span.cnum(self.sess()); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 09c54969ef122..5ed5299e09bc0 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2677,7 +2677,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite let contents = match fs::read_to_string(&path) { Ok(contents) => contents, Err(err) => { - let span = item.span(tcx).inner(); + let span = item.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()); tcx.sess .span_err(span, &format!("failed to read file {}: {}", path.display(), err)); return false; diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index f508808a8b6f5..f37c54e42983f 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -53,6 +53,7 @@ impl LocalSourcesCollector<'_, '_> { fn add_local_source(&mut self, item: &clean::Item) { let sess = self.tcx.sess; let span = item.span(self.tcx); + let Some(span) = span else { return }; // skip all synthetic "files" if !is_real_and_local(span, sess) { return; @@ -109,6 +110,7 @@ impl DocVisitor for SourceCollector<'_, '_> { let tcx = self.cx.tcx(); let span = item.span(tcx); + let Some(span) = span else { return }; let sess = tcx.sess; // If we're not rendering sources, there's nothing to do. diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4c21fd553289b..14d99f3410d43 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -59,7 +59,7 @@ impl JsonRenderer<'_> { id: from_item_id_with_name(item_id, self.tcx, name), crate_id: item_id.krate().as_u32(), name: name.map(|sym| sym.to_string()), - span: self.convert_span(span), + span: span.and_then(|span| self.convert_span(span)), visibility: self.convert_visibility(visibility), docs, attrs, diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 4c6e3eb040d27..48835abf9525b 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -215,7 +215,6 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> { None, ); - let filename = i.span(self.ctx.tcx).filename(self.ctx.sess()); let has_doc_example = tests.found_tests != 0; // The `expect_def_id()` should be okay because `local_def_id_to_hir_id` // would presumably panic if a fake `DefIndex` were passed. @@ -261,13 +260,16 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> { let should_have_docs = !should_be_ignored && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default)); - debug!("counting {:?} {:?} in {:?}", i.type_(), i.name, filename); - self.items.entry(filename).or_default().count_item( - has_docs, - has_doc_example, - should_have_doc_example(self.ctx, i), - should_have_docs, - ); + if let Some(span) = i.span(self.ctx.tcx) { + let filename = span.filename(self.ctx.sess()); + debug!("counting {:?} {:?} in {:?}", i.type_(), i.name, filename); + self.items.entry(filename).or_default().count_item( + has_docs, + has_doc_example, + should_have_doc_example(self.ctx, i), + should_have_docs, + ); + } } } diff --git a/src/test/rustdoc-json/impls/auto.rs b/src/test/rustdoc-json/impls/auto.rs new file mode 100644 index 0000000000000..fb32d7c31bc9b --- /dev/null +++ b/src/test/rustdoc-json/impls/auto.rs @@ -0,0 +1,18 @@ +#![feature(no_core, auto_traits, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +pub auto trait Bar {} + +/// has span +impl Foo { + pub fn baz(&self) {} +} + +// Testing spans, so all tests below code +// @is auto.json "$.index[*][?(@.kind=='impl' && @.inner.synthetic==true)].span" null +// @is - "$.index[*][?(@.docs=='has span')].span.begin" "[10, 0]" +// @is - "$.index[*][?(@.docs=='has span')].span.end" "[12, 1]" +pub struct Foo;