Auto merge of #120417 - matthiaskrgr:rollup-5rszkmd, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #118182 (Properly recover from trailing attr in body) - #119641 (Remove feature not required by `Ipv6Addr::to_cononical` doctest) - #119957 (fix: correct suggestion arg for impl trait) - #120386 (ScopeTree: remove destruction_scopes as unused) - #120398 (Improve handling of numbers in `IntoDiagnosticArg`) - #120399 (Remove myself from review rotation) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7df6f4a15e
11 changed files with 213 additions and 47 deletions
|
@ -58,16 +58,29 @@ macro_rules! into_diagnostic_arg_using_display {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! into_diagnostic_arg_for_number {
|
||||||
|
($( $ty:ty ),+ $(,)?) => {
|
||||||
|
$(
|
||||||
|
impl IntoDiagnosticArg for $ty {
|
||||||
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||||
|
// HACK: `FluentNumber` the underline backing struct represent
|
||||||
|
// numbers using a f64 which can't represent all the i128 numbers
|
||||||
|
// So in order to be able to use fluent selectors and still
|
||||||
|
// have all the numbers representable we only convert numbers
|
||||||
|
// below a certain threshold.
|
||||||
|
if let Ok(n) = TryInto::<i128>::try_into(self) && n >= -100 && n <= 100 {
|
||||||
|
DiagnosticArgValue::Number(n)
|
||||||
|
} else {
|
||||||
|
self.to_string().into_diagnostic_arg()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
into_diagnostic_arg_using_display!(
|
into_diagnostic_arg_using_display!(
|
||||||
ast::ParamKindOrd,
|
ast::ParamKindOrd,
|
||||||
i8,
|
|
||||||
u8,
|
|
||||||
i16,
|
|
||||||
u16,
|
|
||||||
u32,
|
|
||||||
i64,
|
|
||||||
i128,
|
|
||||||
u128,
|
|
||||||
std::io::Error,
|
std::io::Error,
|
||||||
Box<dyn std::error::Error>,
|
Box<dyn std::error::Error>,
|
||||||
std::num::NonZeroU32,
|
std::num::NonZeroU32,
|
||||||
|
@ -82,17 +95,7 @@ into_diagnostic_arg_using_display!(
|
||||||
ExitStatus,
|
ExitStatus,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl IntoDiagnosticArg for i32 {
|
into_diagnostic_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
|
||||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
|
||||||
DiagnosticArgValue::Number(self.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoDiagnosticArg for u64 {
|
|
||||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
|
||||||
DiagnosticArgValue::Number(self.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoDiagnosticArg for bool {
|
impl IntoDiagnosticArg for bool {
|
||||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||||
|
@ -154,12 +157,6 @@ impl IntoDiagnosticArg for PathBuf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoDiagnosticArg for usize {
|
|
||||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
|
||||||
DiagnosticArgValue::Number(self as i128)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoDiagnosticArg for PanicStrategy {
|
impl IntoDiagnosticArg for PanicStrategy {
|
||||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||||
DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
|
DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
|
||||||
|
|
|
@ -1601,23 +1601,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.ty_to_value_string(rcvr_ty.peel_refs())
|
self.ty_to_value_string(rcvr_ty.peel_refs())
|
||||||
};
|
};
|
||||||
if let SelfSource::MethodCall(_) = source {
|
if let SelfSource::MethodCall(_) = source {
|
||||||
let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
|
let first_arg = static_candidates.get(0).and_then(|candidate_source| {
|
||||||
&& let Some(assoc) = self.associated_value(*impl_did, item_name)
|
let (assoc_did, self_ty) = match candidate_source {
|
||||||
&& assoc.kind == ty::AssocKind::Fn
|
CandidateSource::Impl(impl_did) => {
|
||||||
{
|
(*impl_did, self.tcx.type_of(*impl_did).instantiate_identity())
|
||||||
|
}
|
||||||
|
CandidateSource::Trait(trait_did) => (*trait_did, rcvr_ty),
|
||||||
|
};
|
||||||
|
|
||||||
|
let assoc = self.associated_value(assoc_did, item_name)?;
|
||||||
|
if assoc.kind != ty::AssocKind::Fn {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for CandidateSource::Impl, `Self` will be instantiated to a concrete type
|
||||||
|
// but for CandidateSource::Trait, `Self` is still `Self`
|
||||||
let sig = self.tcx.fn_sig(assoc.def_id).instantiate_identity();
|
let sig = self.tcx.fn_sig(assoc.def_id).instantiate_identity();
|
||||||
sig.inputs().skip_binder().get(0).and_then(|first| {
|
sig.inputs().skip_binder().get(0).and_then(|first| {
|
||||||
let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
|
|
||||||
// if the type of first arg is the same as the current impl type, we should take the first arg into assoc function
|
// if the type of first arg is the same as the current impl type, we should take the first arg into assoc function
|
||||||
if first.peel_refs() == impl_ty {
|
let first_ty = first.peel_refs();
|
||||||
|
if first_ty == self_ty || first_ty == self.tcx.types.self_param {
|
||||||
Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
|
Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
});
|
||||||
None
|
|
||||||
};
|
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let args = if let SelfSource::MethodCall(receiver) = source
|
let args = if let SelfSource::MethodCall(receiver) = source
|
||||||
&& let Some(args) = args
|
&& let Some(args) = args
|
||||||
|
|
|
@ -221,9 +221,6 @@ pub struct ScopeTree {
|
||||||
/// variable is declared.
|
/// variable is declared.
|
||||||
var_map: FxIndexMap<hir::ItemLocalId, Scope>,
|
var_map: FxIndexMap<hir::ItemLocalId, Scope>,
|
||||||
|
|
||||||
/// Maps from a `NodeId` to the associated destruction scope (if any).
|
|
||||||
destruction_scopes: FxIndexMap<hir::ItemLocalId, Scope>,
|
|
||||||
|
|
||||||
/// Identifies expressions which, if captured into a temporary, ought to
|
/// Identifies expressions which, if captured into a temporary, ought to
|
||||||
/// have a temporary whose lifetime extends to the end of the enclosing *block*,
|
/// have a temporary whose lifetime extends to the end of the enclosing *block*,
|
||||||
/// and not the enclosing *statement*. Expressions that are not present in this
|
/// and not the enclosing *statement*. Expressions that are not present in this
|
||||||
|
@ -336,11 +333,6 @@ impl ScopeTree {
|
||||||
let prev = self.parent_map.insert(child, p);
|
let prev = self.parent_map.insert(child, p);
|
||||||
assert!(prev.is_none());
|
assert!(prev.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record the destruction scopes for later so we can query them.
|
|
||||||
if let ScopeData::Destruction = child.data {
|
|
||||||
self.destruction_scopes.insert(child.item_local_id(), child);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) {
|
pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) {
|
||||||
|
|
|
@ -791,13 +791,28 @@ impl<'a> Parser<'a> {
|
||||||
&& let [segment] = &attr_kind.item.path.segments[..]
|
&& let [segment] = &attr_kind.item.path.segments[..]
|
||||||
&& segment.ident.name == sym::cfg
|
&& segment.ident.name == sym::cfg
|
||||||
&& let Some(args_span) = attr_kind.item.args.span()
|
&& let Some(args_span) = attr_kind.item.args.span()
|
||||||
&& let Ok(next_attr) = snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None))
|
&& let next_attr = match snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None))
|
||||||
|
{
|
||||||
|
Ok(next_attr) => next_attr,
|
||||||
|
Err(inner_err) => {
|
||||||
|
err.cancel();
|
||||||
|
inner_err.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
&& let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind
|
&& let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind
|
||||||
&& let Some(next_attr_args_span) = next_attr_kind.item.args.span()
|
&& let Some(next_attr_args_span) = next_attr_kind.item.args.span()
|
||||||
&& let [next_segment] = &next_attr_kind.item.path.segments[..]
|
&& let [next_segment] = &next_attr_kind.item.path.segments[..]
|
||||||
&& segment.ident.name == sym::cfg
|
&& segment.ident.name == sym::cfg
|
||||||
&& let Ok(next_expr) = snapshot.parse_expr()
|
|
||||||
{
|
{
|
||||||
|
let next_expr = match snapshot.parse_expr() {
|
||||||
|
Ok(next_expr) => next_expr,
|
||||||
|
Err(inner_err) => {
|
||||||
|
err.cancel();
|
||||||
|
inner_err.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
// We have for sure
|
// We have for sure
|
||||||
// #[cfg(..)]
|
// #[cfg(..)]
|
||||||
// expr
|
// expr
|
||||||
|
|
|
@ -1893,7 +1893,6 @@ impl Ipv6Addr {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(ip)]
|
|
||||||
/// use std::net::Ipv6Addr;
|
/// use std::net::Ipv6Addr;
|
||||||
///
|
///
|
||||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
|
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Issue #118164: recovery path leaving unemitted error behind
|
||||||
|
fn bar() -> String {
|
||||||
|
#[cfg(feature = )]
|
||||||
|
[1, 2, 3].iter().map().collect::<String>() //~ ERROR expected `;`, found `#`
|
||||||
|
#[attr] //~ ERROR expected statement after outer attribute
|
||||||
|
}
|
||||||
|
fn main() {
|
||||||
|
let _ = bar();
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
error: expected `;`, found `#`
|
||||||
|
--> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:4:47
|
||||||
|
|
|
||||||
|
LL | #[cfg(feature = )]
|
||||||
|
| ------------------ only `;` terminated statements or tail expressions are allowed after this attribute
|
||||||
|
LL | [1, 2, 3].iter().map().collect::<String>()
|
||||||
|
| ^ expected `;` here
|
||||||
|
LL | #[attr]
|
||||||
|
| - unexpected token
|
||||||
|
|
|
||||||
|
help: add `;` here
|
||||||
|
|
|
||||||
|
LL | [1, 2, 3].iter().map().collect::<String>();
|
||||||
|
| +
|
||||||
|
help: alternatively, consider surrounding the expression with a block
|
||||||
|
|
|
||||||
|
LL | { [1, 2, 3].iter().map().collect::<String>() }
|
||||||
|
| + +
|
||||||
|
|
||||||
|
error: expected statement after outer attribute
|
||||||
|
--> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:5:5
|
||||||
|
|
|
||||||
|
LL | #[attr]
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
trait M {
|
||||||
|
fn foo(_a: Self);
|
||||||
|
fn bar(_a: Self);
|
||||||
|
fn baz(_a: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl M for A {
|
||||||
|
fn foo(_a: Self) {}
|
||||||
|
fn bar(_a: A) {}
|
||||||
|
fn baz(_a: i32) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _a = A {};
|
||||||
|
A::foo(_a);
|
||||||
|
//~^ ERROR no method named `foo` found
|
||||||
|
A::baz(0);
|
||||||
|
//~^ ERROR no method named `baz` found
|
||||||
|
|
||||||
|
let _b = A {};
|
||||||
|
A::bar(_b);
|
||||||
|
//~^ ERROR no method named `bar` found
|
||||||
|
}
|
29
tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.rs
Normal file
29
tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
trait M {
|
||||||
|
fn foo(_a: Self);
|
||||||
|
fn bar(_a: Self);
|
||||||
|
fn baz(_a: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl M for A {
|
||||||
|
fn foo(_a: Self) {}
|
||||||
|
fn bar(_a: A) {}
|
||||||
|
fn baz(_a: i32) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _a = A {};
|
||||||
|
_a.foo();
|
||||||
|
//~^ ERROR no method named `foo` found
|
||||||
|
_a.baz(0);
|
||||||
|
//~^ ERROR no method named `baz` found
|
||||||
|
|
||||||
|
let _b = A {};
|
||||||
|
_b.bar();
|
||||||
|
//~^ ERROR no method named `bar` found
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
error[E0599]: no method named `foo` found for struct `A` in the current scope
|
||||||
|
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:21:8
|
||||||
|
|
|
||||||
|
LL | struct A {
|
||||||
|
| -------- method `foo` not found for this struct
|
||||||
|
...
|
||||||
|
LL | _a.foo();
|
||||||
|
| ---^^^--
|
||||||
|
| | |
|
||||||
|
| | this is an associated function, not a method
|
||||||
|
| help: use associated function syntax instead: `A::foo(_a)`
|
||||||
|
|
|
||||||
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||||
|
note: the candidate is defined in the trait `M`
|
||||||
|
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:8:5
|
||||||
|
|
|
||||||
|
LL | fn foo(_a: Self);
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0599]: no method named `baz` found for struct `A` in the current scope
|
||||||
|
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:23:8
|
||||||
|
|
|
||||||
|
LL | struct A {
|
||||||
|
| -------- method `baz` not found for this struct
|
||||||
|
...
|
||||||
|
LL | _a.baz(0);
|
||||||
|
| ---^^^---
|
||||||
|
| | |
|
||||||
|
| | this is an associated function, not a method
|
||||||
|
| help: use associated function syntax instead: `A::baz(0)`
|
||||||
|
|
|
||||||
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||||
|
note: the candidate is defined in the trait `M`
|
||||||
|
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:10:5
|
||||||
|
|
|
||||||
|
LL | fn baz(_a: i32);
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0599]: no method named `bar` found for struct `A` in the current scope
|
||||||
|
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:27:8
|
||||||
|
|
|
||||||
|
LL | struct A {
|
||||||
|
| -------- method `bar` not found for this struct
|
||||||
|
...
|
||||||
|
LL | _b.bar();
|
||||||
|
| ---^^^--
|
||||||
|
| | |
|
||||||
|
| | this is an associated function, not a method
|
||||||
|
| help: use associated function syntax instead: `A::bar(_b)`
|
||||||
|
|
|
||||||
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||||
|
note: the candidate is defined in the trait `M`
|
||||||
|
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:9:5
|
||||||
|
|
|
||||||
|
LL | fn bar(_a: Self);
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
|
@ -663,7 +663,6 @@ libs = [
|
||||||
"@joshtriplett",
|
"@joshtriplett",
|
||||||
"@Mark-Simulacrum",
|
"@Mark-Simulacrum",
|
||||||
"@m-ou-se",
|
"@m-ou-se",
|
||||||
"@thomcc",
|
|
||||||
]
|
]
|
||||||
bootstrap = [
|
bootstrap = [
|
||||||
"@Mark-Simulacrum",
|
"@Mark-Simulacrum",
|
||||||
|
@ -803,7 +802,7 @@ project-stable-mir = [
|
||||||
"/library/panic_unwind" = ["libs"]
|
"/library/panic_unwind" = ["libs"]
|
||||||
"/library/proc_macro" = ["@petrochenkov"]
|
"/library/proc_macro" = ["@petrochenkov"]
|
||||||
"/library/std" = ["libs"]
|
"/library/std" = ["libs"]
|
||||||
"/library/std/src/sys/pal/windows" = ["@ChrisDenton", "@thomcc"]
|
"/library/std/src/sys/pal/windows" = ["@ChrisDenton"]
|
||||||
"/library/stdarch" = ["libs"]
|
"/library/stdarch" = ["libs"]
|
||||||
"/library/test" = ["libs"]
|
"/library/test" = ["libs"]
|
||||||
"/src/bootstrap" = ["bootstrap"]
|
"/src/bootstrap" = ["bootstrap"]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue