profile
viewpoint
Esteban Kuber estebank San Francisco, CA http://esteban.kuber.com.ar/resume/ Off-by-one error fixer/introducer. I 💖@rust-lang⚙️ PST tz

estebank/galvanize 7

Galvanize: Pure Rust CDB reader/writer

commure/hazy 5

OpaqueDebug implementation

estebank/jsmk 4

Javascript Canvas based fighting game engine

estebank/panorama 2

HTML5+JS diff display

estebank/resume 2

My HTML resume. It's self-contained with no external dependencies. Emphasis on readability across User Agents.

estebank/difference.rs 1

Rust text diffing and assertion library

estebank/galvanize_cli 1

CLI Tool to interact with CDBs.

estebank/pysmell 1

PySmell is an attempt to create an IDE completion helper for python.

estebank/atom 0

trying things out

pull request commentrust-lang/rustc-guide

Add diagnostics ICE-breakers page

@mark-i-m I'll fix the typo soon, this fell through the cracks of my queue.

estebank

comment created time in 5 hours

Pull request review commentrust-lang/rust

Accept `Enum::<Param>::Variant {}` over `Enum::Variant::<Param> {}`

 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {         path_segs     } +    fn lint_type_param_on_variant_ctor(&self, segments: &[hir::PathSegment<'_>]) {+        // Doing this to get around rustfmt-caused line too long.+        use hir::PathSegment as P;+        if let [.., prev, P { ident, hir_id: Some(hir_id), args: Some(args), .. }] = segments {+            let sp = args.span;+            if sp.hi() == sp.lo() || sp == DUMMY_SP || sp.parent().is_some() {+                // The params were not written by the user, but rather derived. These are expected.+                // `Enum::Variant` where `Variant` has inferred lifetimes.+                return;+            }

But if none of the PathSegments have the elision lifetimes injected (in src/librustc_ast_lowering/path.rs) then you get knock down errors about the type for a HirId not existing .

estebank

comment created time in 5 hours

push eventestebank/rust

Esteban Küber

commit sha 01734905f8989951d13c16362ce54598906d4759

Reword message

view details

Esteban Küber

commit sha c02e56a9003624e87bad8b4a93703be030e03aed

Do not suggest implementing traits if present in predicates

view details

push time in 8 hours

Pull request review commentrust-lang/rust

Accept `Enum::<Param>::Variant {}` over `Enum::Variant::<Param> {}`

 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {         path_segs     } +    fn lint_type_param_on_variant_ctor(&self, segments: &[hir::PathSegment<'_>]) {+        // Doing this to get around rustfmt-caused line too long.+        use hir::PathSegment as P;+        if let [.., prev, P { ident, hir_id: Some(hir_id), args: Some(args), .. }] = segments {+            let sp = args.span;+            if sp.hi() == sp.lo() || sp == DUMMY_SP || sp.parent().is_some() {+                // The params were not written by the user, but rather derived. These are expected.+                // `Enum::Variant` where `Variant` has inferred lifetimes.+                return;+            }

Agree. It's hacky as hell.

you can get rid of the lifetimes for now

How?

they shouldn't be added to value paths anyway

I've spent too much time trying to figure out of a way of making this change without affecting currently accepted code.

estebank

comment created time in 8 hours

Pull request review commentrust-lang/rust

Accept `Enum::<Param>::Variant {}` over `Enum::Variant::<Param> {}`

 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {             item_def_id,             item_segment,             trait_ref.substs,+            generic_arg_position,         );          debug!("qpath_to_ty: trait_ref={:?}", trait_ref);          self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))     } +    pub fn prohibit_multiple_params<'a, T: IntoIterator<Item = &'a hir::PathSegment<'a>>>(+        &self,+        segments: T,+    ) -> bool {+        let segments_with_params = segments+            .into_iter()+            .filter_map(|segment| segment.args.map(|arg| arg.span))+            .collect::<Vec<_>>();+        if segments_with_params.len() <= 1 {+            return false;+        }+        self.tcx()+            .sess+            .struct_span_err(+                segments_with_params,+                "multiple segments with type parameters are not allowed",+            )+            .note("only a single path segment can specify type parameters")+            .emit();+        true+    }

I think this is unnecessarily complicated, it doesn't distinguish this "enum vs variant" situation from others (e.g. trying to pass generic args to a mod) and it's wrong with generic associated items like methods or GATs.

That check is being done when called. If it were called without that check it would indeed be incorrect.

This could be a help message on the error from prohibit_generics, such as pointing to the enum segment and saying "this segment already specified generic args for the enum" or something.

Wanted to separate this from E0109 to potentially give it its own error code to explain that this will never be supported as opposed to the more generic current error.

estebank

comment created time in 8 hours

Pull request review commentrust-lang/rust

Add more context to E0599 errors

+error[E0599]: no method named `foo` found for reference `&Foo<T>` in the current scope+  --> $DIR/missing-trait-bounds-for-method-call.rs:14:14+   |+LL | struct Foo<T> {+   | ------------- doesn't satisfy `Foo<T>: Bar`+...+LL |         self.foo();+   |              ^^^ method not found in `&Foo<T>`+   |+   = note: the method `foo` exists but the following trait bounds were not satisfied:+           `T: Bar`+           which is required by `Foo<T>: Bar`+           `T: std::default::Default`+           which is required by `Foo<T>: Bar`+help: consider restricting the type parameters to satisfy the obligations+   |+LL | struct Foo<T> where T: Bar, T: std::default::Default {+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++error[E0599]: no method named `foo` found for reference `&Fin<T>` in the current scope+  --> $DIR/missing-trait-bounds-for-method-call.rs:27:14+   |+LL | struct Fin<T> where T: Bar {+   | -------------------------- doesn't satisfy `Fin<T>: Bar`+...+LL |         self.foo();+   |              ^^^ method not found in `&Fin<T>`+   |+   = note: the method `foo` exists but the following trait bounds were not satisfied:+           `T: std::default::Default`+           which is required by `Fin<T>: Bar`+help: consider restricting the type parameter to satisfy the obligation

What about "consider restricting the type parameter to satisfy the trait bound"?

estebank

comment created time in 8 hours

pull request commentrust-lang/rust

typeck: use `Pattern` obligation cause more for better diagnostics

@bors r+

Centril

comment created time in 9 hours

issue commentrust-lang/rust

Possibly incorrect syntax `Enum::<Type, Params>::Variant` allowed since 1.33

Answering my own questions based on the conversations on discord. All of the following should be allowed:

pub enum Foo<'a, T> {
    Struct {},
    Tuple(),
    Unit,
    Usage(&'a T),
}
pub fn main() {
    let foo = Foo::<String>::Unit;
    let foo = Foo::<String>::Tuple();
    let foo = Foo::<String>::Struct {};
    let foo = Foo::Unit::<String>;
    let foo = Foo::Tuple::<String>();
    let foo = Foo::Struct::<String> {};
}

Based on FIXMEs and the conversation, the later 3 should be linted against but must remain valid for backwards compatibility.

#69363 fixes this ticket.

estebank

comment created time in 19 hours

Pull request review commentrust-lang/rust

Add more context to E0599 errors

+error[E0599]: no method named `foo` found for reference `&Foo<T>` in the current scope+  --> $DIR/missing-trait-bounds-for-method-call.rs:14:14+   |+LL | struct Foo<T> {+   | ------------- doesn't satisfy `Foo<T>: Bar`+...+LL | trait Bar {+   | --------- `Bar` defines an item `foo`, perhaps you need to implement it+...+LL |         self.foo();+   |              ^^^ method not found in `&Foo<T>`

In the new commit, this test looks like this now:

Screen Shot 2020-02-24 at 10 38 59 PM

It is a very niche case, but with this we handle it well enough, I think.

estebank

comment created time in 20 hours

push eventestebank/rust

Esteban Küber

commit sha c02de78ca03219713eb8979f712b2e3252df8c1a

Reduce verbosity when suggesting restricting type params

view details

push time in 20 hours

pull request commentrust-lang/rust

remove redundant clones and import

@bors r+ rollup

matthiaskrgr

comment created time in a day

issue commentrust-lang/rust

Regression in helpful compiler error message when working with lifetimes

@nikomatsakis fair. Keep in mind that the case above is exercising a more complex case than the more likely one:

error: `impl` item signature doesn't match `trait` item signature
  --> file5.rs:37:5
   |
31 | pub trait Bar<To> {
   |               -- this type parameter might not have a lifetime compatible with the `impl`
32 |     fn get_relation(&self) -> To;
   |     -----------------------------
   |     |                         |
   |     |                         you might want to borrow this type parameter in the trait to make it match the `impl`
   |     expected `fn(&Article) -> &ProofReader`
...
37 |     fn get_relation(&self) -> &ProofReader {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Article) -> &ProofReader`
   |
   = note: expected `fn(&Article) -> &ProofReader`
              found `fn(&Article) -> &ProofReader`
   = note: the lifetime requirements from the `trait` could not be satisfied by the `impl`
   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output

It is also difficult because anything I remove I feel like I'm hiding useful information.

petergarnaes

comment created time in a day

pull request commentrust-lang/rust

Minor refactoring of statement parsing

r=me after addressing that minor nitpick

Centril

comment created time in a day

Pull request review commentrust-lang/rust

Minor refactoring of statement parsing

 impl<'a> Parser<'a> {         let attrs = self.parse_outer_attributes()?;         let lo = self.token.span; -        if self.eat_keyword(kw::Let) {-            return self.parse_local_mk(lo, attrs.into()).map(Some);-        }-        if self.is_kw_followed_by_ident(kw::Mut) {-            return self.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut");-        }-        if self.is_kw_followed_by_ident(kw::Auto) {+        let stmt = if self.eat_keyword(kw::Let) {+            self.parse_local_mk(lo, attrs.into())?+        } else if self.is_kw_followed_by_ident(kw::Mut) {+            self.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut")?+        } else if self.is_kw_followed_by_ident(kw::Auto) {             self.bump(); // `auto`             let msg = "write `let` instead of `auto` to introduce a new variable";-            return self.recover_stmt_local(lo, attrs.into(), msg, "let");-        }-        if self.is_kw_followed_by_ident(sym::var) {+            self.recover_stmt_local(lo, attrs.into(), msg, "let")?+        } else if self.is_kw_followed_by_ident(sym::var) {             self.bump(); // `var`             let msg = "write `let` instead of `var` to introduce a new variable";-            return self.recover_stmt_local(lo, attrs.into(), msg, "let");-        }--        // Starts like a simple path, being careful to avoid contextual keywords,-        // e.g., `union`, items with `crate` visibility, or `auto trait` items.-        // We aim to parse an arbitrary path `a::b` but not something that starts like a path-        // (1 token), but it fact not a path. Also, we avoid stealing syntax from `parse_item_`.-        if self.token.is_path_start() && !self.token.is_qpath_start() && !self.is_path_start_item()+            self.recover_stmt_local(lo, attrs.into(), msg, "let")?+        } else if self.token.is_path_start()+            && !self.token.is_qpath_start()+            && !self.is_path_start_item()         {-            let path = self.parse_path(PathStyle::Expr)?;--            if self.eat(&token::Not) {-                return self.parse_stmt_mac(lo, attrs.into(), path);-            }--            let expr = if self.check(&token::OpenDelim(token::Brace)) {-                self.parse_struct_expr(lo, path, AttrVec::new())?-            } else {-                let hi = self.prev_span;-                self.mk_expr(lo.to(hi), ExprKind::Path(None, path), AttrVec::new())-            };--            let expr = self.with_res(Restrictions::STMT_EXPR, |this| {-                let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;-                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))-            })?;-            return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Expr(expr))));+            // We have avoided contextual keywords like `union`, items with `crate` visibility,+            // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something+            // that starts like a path (1 token), but it fact not a path.+            // Also, we avoid stealing syntax from `parse_item_`.+            self.parse_stmt_path_start(lo, attrs)?+        } else if let Some(item) = self.parse_stmt_item(attrs.clone())? {+            // FIXME: Bad copy of attrs+            self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))         }--        // FIXME: Bad copy of attrs-        let old_directory_ownership =-            mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);-        let item = self.parse_item_common(attrs.clone(), false, true, |_| true)?;-        self.directory.ownership = old_directory_ownership;--        if let Some(item) = item {-            return Ok(Some(self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))));-        }-         // Do not attempt to parse an expression if we're done here.-        if self.token == token::Semi {+        else if self.token == token::Semi {

merge with prior line

Centril

comment created time in a day

Pull request review commentrust-lang/rust

Minor refactoring of statement parsing

 impl<'a> Parser<'a> {         let attrs = self.parse_outer_attributes()?;         let lo = self.token.span; -        if self.eat_keyword(kw::Let) {-            return self.parse_local_mk(lo, attrs.into()).map(Some);-        }-        if self.is_kw_followed_by_ident(kw::Mut) {-            return self.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut");-        }-        if self.is_kw_followed_by_ident(kw::Auto) {+        let stmt = if self.eat_keyword(kw::Let) {+            self.parse_local_mk(lo, attrs.into())?+        } else if self.is_kw_followed_by_ident(kw::Mut) {+            self.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut")?+        } else if self.is_kw_followed_by_ident(kw::Auto) {             self.bump(); // `auto`             let msg = "write `let` instead of `auto` to introduce a new variable";-            return self.recover_stmt_local(lo, attrs.into(), msg, "let");-        }-        if self.is_kw_followed_by_ident(sym::var) {+            self.recover_stmt_local(lo, attrs.into(), msg, "let")?+        } else if self.is_kw_followed_by_ident(sym::var) {             self.bump(); // `var`             let msg = "write `let` instead of `var` to introduce a new variable";-            return self.recover_stmt_local(lo, attrs.into(), msg, "let");-        }--        // Starts like a simple path, being careful to avoid contextual keywords,-        // e.g., `union`, items with `crate` visibility, or `auto trait` items.-        // We aim to parse an arbitrary path `a::b` but not something that starts like a path-        // (1 token), but it fact not a path. Also, we avoid stealing syntax from `parse_item_`.-        if self.token.is_path_start() && !self.token.is_qpath_start() && !self.is_path_start_item()+            self.recover_stmt_local(lo, attrs.into(), msg, "let")?+        } else if self.token.is_path_start()+            && !self.token.is_qpath_start()+            && !self.is_path_start_item()         {-            let path = self.parse_path(PathStyle::Expr)?;--            if self.eat(&token::Not) {-                return self.parse_stmt_mac(lo, attrs.into(), path);-            }--            let expr = if self.check(&token::OpenDelim(token::Brace)) {-                self.parse_struct_expr(lo, path, AttrVec::new())?-            } else {-                let hi = self.prev_span;-                self.mk_expr(lo.to(hi), ExprKind::Path(None, path), AttrVec::new())-            };--            let expr = self.with_res(Restrictions::STMT_EXPR, |this| {-                let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;-                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))-            })?;-            return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Expr(expr))));+            // We have avoided contextual keywords like `union`, items with `crate` visibility,+            // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something+            // that starts like a path (1 token), but it fact not a path.+            // Also, we avoid stealing syntax from `parse_item_`.+            self.parse_stmt_path_start(lo, attrs)?+        } else if let Some(item) = self.parse_stmt_item(attrs.clone())? {+            // FIXME: Bad copy of attrs+            self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))

👀

Centril

comment created time in a day

issue commentrust-lang/rust

"note: method exists but trait bounds not satisfied" could be better

Current output in #69255:

error[E0599]: no method named `join` found for struct `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>` in the current scope
   --> file5.rs:16:43
    |
16  |     a.iter().map(|x| x.to_str().unwrap()).join(":");
    |                                           ^^^^ method not found in `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>`
    |
   ::: /rust/src/libcore/iter/adapters/mod.rs:751:1
    |
751 | pub struct Map<I, F> {
    | --------------------
    | |
    | doesn't satisfy `<_ as std::iter::Iterator>::Item = std::string::String`
    | doesn't satisfy `_: JoinWithString`
    |
    = note: the method `join` exists but the following trait bounds were not satisfied:
            `<std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]> as std::iter::Iterator>::Item = std::string::String`
            which is required by `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: JoinWithString`
            `<&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]> as std::iter::Iterator>::Item = std::string::String`
            which is required by `&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: JoinWithString`
            `&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: std::iter::Iterator`
            which is required by `&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: JoinWithString`
            `<&mut std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]> as std::iter::Iterator>::Item = std::string::String`
            which is required by `&mut std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: JoinWithString`
    = help: items from traits can only be used if the trait is implemented and in scope
note: `JoinWithString` defines an item `join`, perhaps you need to implement it
   --> file5.rs:1:1
    |
1   | pub trait JoinWithString {
    | ^^^^^^^^^^^^^^^^^^^^^^^^

which would look like this in end user's envs:

error[E0599]: no method named `join` found for struct `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>` in the current scope
   --> file5.rs:16:43
    |
16  |     a.iter().map(|x| x.to_str().unwrap()).join(":");
    |                                           ^^^^ method not found in `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>`
    |
    = note: the method `join` exists but the following trait bounds were not satisfied:
            `<std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]> as std::iter::Iterator>::Item = std::string::String`
            which is required by `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: JoinWithString`
            `<&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]> as std::iter::Iterator>::Item = std::string::String`
            which is required by `&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: JoinWithString`
            `&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: std::iter::Iterator`
            which is required by `&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: JoinWithString`
            `<&mut std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]> as std::iter::Iterator>::Item = std::string::String`
            which is required by `&mut std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:16:18: 16:41]>: JoinWithString`
    = help: items from traits can only be used if the trait is implemented and in scope
note: `JoinWithString` defines an item `join`, perhaps you need to implement it
   --> file5.rs:1:1
    |
1   | pub trait JoinWithString {
    | ^^^^^^^^^^^^^^^^^^^^^^^^
durka

comment created time in a day

push eventestebank/rust

Esteban Küber

commit sha a66599f3a0d69478c5bb985caa42d054b5844d0c

keep predicate order and tweak output

view details

push time in a day

Pull request review commentrust-lang/rust

Add more context to E0599 errors

+error[E0599]: no method named `foo` found for reference `&Foo<T>` in the current scope+  --> $DIR/missing-trait-bounds-for-method-call.rs:14:14+   |+LL | struct Foo<T> {+   | ------------- doesn't satisfy `Foo<T>: Bar`+...+LL | trait Bar {+   | --------- `Bar` defines an item `foo`, perhaps you need to implement it+...+LL |         self.foo();+   |              ^^^ method not found in `&Foo<T>`

@tmandry What do you think of this?

Screen Shot 2020-02-24 at 6 53 40 PM

estebank

comment created time in a day

issue closedrust-lang/rust

Suggest borrow when pattern ergonomics cause mismatched lifetimes

I encountered the following diagnostic:

error: lifetime may not live long enough
   --> src/librustc_typeck/check/method/suggest.rs:667:57
    |
667 |                     bound_list.dedup_by_key(|(_, path)| path); // #35677
    |                                              ---------- ^^^^ returning this value requires that `'1` must outlive `'2`
    |                                              |        |
    |                                              |        return type of closure is &'2 mut std::string::String
    |                                              has type `&'1 mut (usize, std::string::String)`

The reason it failed is because it is relying on pattern ergonomics to autoborrow the tuple argument, but because of this it fails to unify the lifetimes as a normal closure would. The compiler should detect this case and suggest the appropriate syntax.

closed time in a day

estebank

issue commentrust-lang/rust

internal compiler error: no type for node HirId ...

@dwrensha on a very cursory look that patch looks reasonable.

dwrensha

comment created time in a day

issue openedrust-lang/rust

Suggest borrow when pattern ergonomics cause mismatched lifetimes

I encountered the following diagnostic:

error: lifetime may not live long enough
   --> src/librustc_typeck/check/method/suggest.rs:667:57
    |
667 |                     bound_list.dedup_by_key(|(_, path)| path); // #35677
    |                                              ---------- ^^^^ returning this value requires that `'1` must outlive `'2`
    |                                              |        |
    |                                              |        return type of closure is &'2 mut std::string::String
    |                                              has type `&'1 mut (usize, std::string::String)`

The reason it failed is because it is relying on pattern ergonomics to autoborrow the tuple argument, but because of this it fails to unify the lifetimes as a normal closure would. The compiler should detect this case and suggest |&(_, path)| &path instead.

created time in a day

push eventestebank/rust

Esteban Küber

commit sha 63379aa65ca88eff9060ae8ee16a0717104f657b

Allow lint `type_param_on_variant_ctor` by default

view details

push time in a day

pull request commentrust-lang/rust

Accept `Enum::<Param>::Variant {}` over `Enum::Variant::<Param> {}`

I've got a commit to make the lint allow by default if that is preferable.

estebank

comment created time in a day

Pull request review commentrust-lang/rust

EXPERIMENT: Recover on stmts/exprs at module level, suggesting to wrap in function

 impl<'a> Parser<'a> {         Ok(Mod { inner: inner_lo.to(hi), items, inline: true })     } +    fn parse_item_in_mod(+        &mut self,+        term: &TokenKind,+        stuck: &mut bool,+    ) -> PResult<'a, Option<Option<P<ast::Item>>>> {+        match self.parse_item()? {+            // We just made progress and we might have statements following this item.+            i @ Some(_) => {+                *stuck = false;+                Ok(Some(i))+            }+            // No progress and the previous attempt at statements failed, so terminate the loop.+            None if *stuck => Ok(None),+            None => Ok(self.recover_stmts_as_item(term, stuck)?.then_some(None)),+        }+    }++    /// Parse a contiguous list of statements until we reach the terminating token or EOF.+    /// When any statements were parsed, perform recovery and suggest wrapping the statements+    /// inside a function. If `stuck` becomes `true`, then this method should not be called+    /// unless we have advanced the cursor.+    fn recover_stmts_as_item(&mut self, term: &TokenKind, stuck: &mut bool) -> PResult<'a, bool> {+        let lo = self.token.span;+        let mut stmts = vec![];+        while ![term, &token::Eof].contains(&&self.token.kind) {+            let old_expected = std::mem::take(&mut self.expected_tokens);+            let snapshot = self.clone();+            let stmt = self.parse_full_stmt(true);+            self.expected_tokens = old_expected; // Restore expected tokens to before recovery.+            match stmt {+                Ok(None) => break,+                Ok(Some(stmt)) => stmts.push(stmt),+                Err(mut err) => {+                    // We couldn't parse as a statement. Rewind to the last one we could for.+                    // Also notify the caller that we made no progress, meaning that the method+                    // should not be called again to avoid non-termination.+                    err.cancel();+                    *self = snapshot;+                    *stuck = true;+                    break;+                }+            }+        }++        let recovered = !stmts.is_empty();+        if recovered {+            // We parsed some statements and have recovered, so let's emit an error.+            self.error_stmts_as_item_suggest_fn(lo, stmts);+        }+        Ok(recovered)+    }++    fn error_stmts_as_item_suggest_fn(&self, lo: Span, stmts: Vec<ast::Stmt>) {+        use syntax::ast::*;++        let span = lo.to(self.prev_span);+        let spans: MultiSpan = match &*stmts {+            [] | [_] => span.into(),+            [x, .., y] => vec![x.span, y.span].into(),

I mean that the alternative was a single x.span.until(y.span).

Centril

comment created time in a day

pull request commentrust-lang/rust

Backport only: avoid ICE on bad placeholder type

@bors r=Centril

I'll rebase the branch with proper fix. Let's land this quickly to fix the ICE.

estebank

comment created time in a day

push eventestebank/rust

Esteban Küber

commit sha 0339831b12fdb7a6502fd9db164dc6017bf6c3da

Lint against `E::V::<P>`, suggest `E::<P>::V`

view details

Esteban Küber

commit sha 9d58e12af574dff2085abcd3fa3e32d22b7d66ff

Specific error for +1 path segments with params

view details

push time in a day

Pull request review commentrust-lang/rust

EXPERIMENT: Recover on stmts/exprs at module level, suggesting to wrap in function

 impl<'a> Parser<'a> {      /// Parses associated items.     fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option<Option<P<AssocItem>>>> {-        Ok(self.parse_item_(req_name)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {+        let item = self.parse_item_(req_name)?;+        Ok(item.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {

This should handle the missing closing brace case somehow.

Centril

comment created time in a day

Pull request review commentrust-lang/rust

EXPERIMENT: Recover on stmts/exprs at module level, suggesting to wrap in function

 impl<'a> Parser<'a> {         Ok(Mod { inner: inner_lo.to(hi), items, inline: true })     } +    fn parse_item_in_mod(+        &mut self,+        term: &TokenKind,+        stuck: &mut bool,+    ) -> PResult<'a, Option<Option<P<ast::Item>>>> {+        match self.parse_item()? {+            // We just made progress and we might have statements following this item.+            i @ Some(_) => {+                *stuck = false;+                Ok(Some(i))+            }+            // No progress and the previous attempt at statements failed, so terminate the loop.+            None if *stuck => Ok(None),+            None => Ok(self.recover_stmts_as_item(term, stuck)?.then_some(None)),+        }+    }++    /// Parse a contiguous list of statements until we reach the terminating token or EOF.+    /// When any statements were parsed, perform recovery and suggest wrapping the statements+    /// inside a function. If `stuck` becomes `true`, then this method should not be called+    /// unless we have advanced the cursor.+    fn recover_stmts_as_item(&mut self, term: &TokenKind, stuck: &mut bool) -> PResult<'a, bool> {+        let lo = self.token.span;+        let mut stmts = vec![];+        while ![term, &token::Eof].contains(&&self.token.kind) {+            let old_expected = std::mem::take(&mut self.expected_tokens);+            let snapshot = self.clone();+            let stmt = self.parse_full_stmt(true);+            self.expected_tokens = old_expected; // Restore expected tokens to before recovery.+            match stmt {+                Ok(None) => break,+                Ok(Some(stmt)) => stmts.push(stmt),+                Err(mut err) => {+                    // We couldn't parse as a statement. Rewind to the last one we could for.+                    // Also notify the caller that we made no progress, meaning that the method+                    // should not be called again to avoid non-termination.+                    err.cancel();+                    *self = snapshot;+                    *stuck = true;+                    break;+                }+            }+        }++        let recovered = !stmts.is_empty();+        if recovered {+            // We parsed some statements and have recovered, so let's emit an error.+            self.error_stmts_as_item_suggest_fn(lo, stmts);+        }+        Ok(recovered)+    }++    fn error_stmts_as_item_suggest_fn(&self, lo: Span, stmts: Vec<ast::Stmt>) {+        use syntax::ast::*;++        let span = lo.to(self.prev_span);+        let spans: MultiSpan = match &*stmts {+            [] | [_] => span.into(),+            [x, .., y] => vec![x.span, y.span].into(),+        };++        // Perform coarse grained inference about returns.+        // We use this to tell whether `main` is an acceptable name+        // and if `-> _` or `-> Result<_, _>` should be used instead of defaulting to unit.+        #[derive(Default)]+        struct RetInfer(bool, bool, bool);+        let RetInfer(has_ret_unit, has_ret_expr, has_try_expr) = {+            impl Visitor<'_> for RetInfer {+                fn visit_expr_post(&mut self, expr: &Expr) {+                    match expr.kind {+                        ExprKind::Ret(None) => self.0 = true,    // `return`+                        ExprKind::Ret(Some(_)) => self.1 = true, // `return $expr`+                        ExprKind::Try(_) => self.2 = true,       // `expr?`+                        _ => {}+                    }+                }+            }+            let mut visitor = RetInfer::default();+            for stmt in &stmts {+                visitor.visit_stmt(stmt);+            }+            if let StmtKind::Expr(_) = &stmts.last().unwrap().kind {+                visitor.1 = true; // The tail expression.

Up to a point, after we've shown the user how to write a function, if they forget to add a return type we'll guide them in the right direction in subsequent errors.

Centril

comment created time in a day

Pull request review commentrust-lang/rust

EXPERIMENT: Recover on stmts/exprs at module level, suggesting to wrap in function

 impl<'a> Parser<'a> {         Ok(Mod { inner: inner_lo.to(hi), items, inline: true })     } +    fn parse_item_in_mod(+        &mut self,+        term: &TokenKind,+        stuck: &mut bool,+    ) -> PResult<'a, Option<Option<P<ast::Item>>>> {+        match self.parse_item()? {+            // We just made progress and we might have statements following this item.+            i @ Some(_) => {+                *stuck = false;+                Ok(Some(i))+            }+            // No progress and the previous attempt at statements failed, so terminate the loop.+            None if *stuck => Ok(None),+            None => Ok(self.recover_stmts_as_item(term, stuck)?.then_some(None)),+        }+    }++    /// Parse a contiguous list of statements until we reach the terminating token or EOF.+    /// When any statements were parsed, perform recovery and suggest wrapping the statements+    /// inside a function. If `stuck` becomes `true`, then this method should not be called+    /// unless we have advanced the cursor.+    fn recover_stmts_as_item(&mut self, term: &TokenKind, stuck: &mut bool) -> PResult<'a, bool> {+        let lo = self.token.span;+        let mut stmts = vec![];+        while ![term, &token::Eof].contains(&&self.token.kind) {+            let old_expected = std::mem::take(&mut self.expected_tokens);+            let snapshot = self.clone();+            let stmt = self.parse_full_stmt(true);+            self.expected_tokens = old_expected; // Restore expected tokens to before recovery.+            match stmt {+                Ok(None) => break,+                Ok(Some(stmt)) => stmts.push(stmt),+                Err(mut err) => {+                    // We couldn't parse as a statement. Rewind to the last one we could for.+                    // Also notify the caller that we made no progress, meaning that the method+                    // should not be called again to avoid non-termination.+                    err.cancel();+                    *self = snapshot;+                    *stuck = true;+                    break;+                }+            }+        }++        let recovered = !stmts.is_empty();+        if recovered {+            // We parsed some statements and have recovered, so let's emit an error.+            self.error_stmts_as_item_suggest_fn(lo, stmts);+        }+        Ok(recovered)+    }++    fn error_stmts_as_item_suggest_fn(&self, lo: Span, stmts: Vec<ast::Stmt>) {+        use syntax::ast::*;++        let span = lo.to(self.prev_span);+        let spans: MultiSpan = match &*stmts {+            [] | [_] => span.into(),+            [x, .., y] => vec![x.span, y.span].into(),+        };++        // Perform coarse grained inference about returns.+        // We use this to tell whether `main` is an acceptable name+        // and if `-> _` or `-> Result<_, _>` should be used instead of defaulting to unit.+        #[derive(Default)]+        struct RetInfer(bool, bool, bool);+        let RetInfer(has_ret_unit, has_ret_expr, has_try_expr) = {+            impl Visitor<'_> for RetInfer {+                fn visit_expr_post(&mut self, expr: &Expr) {+                    match expr.kind {+                        ExprKind::Ret(None) => self.0 = true,    // `return`+                        ExprKind::Ret(Some(_)) => self.1 = true, // `return $expr`+                        ExprKind::Try(_) => self.2 = true,       // `expr?`+                        _ => {}+                    }+                }+            }+            let mut visitor = RetInfer::default();+            for stmt in &stmts {+                visitor.visit_stmt(stmt);+            }+            if let StmtKind::Expr(_) = &stmts.last().unwrap().kind {+                visitor.1 = true; // The tail expression.

The tail expression will be somewhat arbitrary in real code. Don't know if this part is worth it or it will be noisier than we'd wish.

Centril

comment created time in a day

Pull request review commentrust-lang/rust

EXPERIMENT: Recover on stmts/exprs at module level, suggesting to wrap in function

 impl<'a> Parser<'a> {         Ok(Mod { inner: inner_lo.to(hi), items, inline: true })     } +    fn parse_item_in_mod(+        &mut self,+        term: &TokenKind,+        stuck: &mut bool,+    ) -> PResult<'a, Option<Option<P<ast::Item>>>> {+        match self.parse_item()? {+            // We just made progress and we might have statements following this item.+            i @ Some(_) => {+                *stuck = false;+                Ok(Some(i))+            }+            // No progress and the previous attempt at statements failed, so terminate the loop.+            None if *stuck => Ok(None),+            None => Ok(self.recover_stmts_as_item(term, stuck)?.then_some(None)),+        }+    }++    /// Parse a contiguous list of statements until we reach the terminating token or EOF.+    /// When any statements were parsed, perform recovery and suggest wrapping the statements+    /// inside a function. If `stuck` becomes `true`, then this method should not be called+    /// unless we have advanced the cursor.+    fn recover_stmts_as_item(&mut self, term: &TokenKind, stuck: &mut bool) -> PResult<'a, bool> {+        let lo = self.token.span;+        let mut stmts = vec![];+        while ![term, &token::Eof].contains(&&self.token.kind) {+            let old_expected = std::mem::take(&mut self.expected_tokens);+            let snapshot = self.clone();+            let stmt = self.parse_full_stmt(true);+            self.expected_tokens = old_expected; // Restore expected tokens to before recovery.+            match stmt {+                Ok(None) => break,+                Ok(Some(stmt)) => stmts.push(stmt),+                Err(mut err) => {+                    // We couldn't parse as a statement. Rewind to the last one we could for.+                    // Also notify the caller that we made no progress, meaning that the method+                    // should not be called again to avoid non-termination.+                    err.cancel();+                    *self = snapshot;+                    *stuck = true;+                    break;+                }+            }+        }++        let recovered = !stmts.is_empty();+        if recovered {+            // We parsed some statements and have recovered, so let's emit an error.+            self.error_stmts_as_item_suggest_fn(lo, stmts);+        }+        Ok(recovered)+    }++    fn error_stmts_as_item_suggest_fn(&self, lo: Span, stmts: Vec<ast::Stmt>) {+        use syntax::ast::*;++        let span = lo.to(self.prev_span);+        let spans: MultiSpan = match &*stmts {+            [] | [_] => span.into(),+            [x, .., y] => vec![x.span, y.span].into(),

I'm guessing that you didn't like the multiline span output for these?

Centril

comment created time in a day

Pull request review commentrust-lang/rust

EXPERIMENT: Recover on stmts/exprs at module level, suggesting to wrap in function

 impl<'a> Parser<'a> {     }      /// Parses an item macro, e.g., `item!();`.-    fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, Mac> {-        let path = self.parse_path(PathStyle::Mod)?; // `foo::bar`-        self.expect(&token::Not)?; // `!`+    fn parse_item_macro(&mut self, vis: &Visibility, mod_stmt: bool) -> PResult<'a, Option<Mac>> {+        let parse_prefix = |p: &mut Self| -> PResult<'a, ast::Path> {+            let path = p.parse_path(PathStyle::Mod)?; // `foo::bar`+            p.expect(&token::Not)?; // `!`+            Ok(path)+        };+        let path = if mod_stmt {+            // We're in statement-as-module-item recovery mode.+            // To avoid "stealing" syntax from e.g. `x.f()` as a module-level statement,+            // we backtrack if we failed to parse `$path!`; after we have, we commit firmly.+            // This is only done when `mod_stmt` holds to avoid backtracking inside functions.+            let snapshot = self.clone();+            match parse_prefix(self) {+                Ok(path) => path,+                Err(mut err) => {+                    // Assert that this is only for diagnostics!+                    // This is a safeguard against breaking LL(k) accidentally in the spec,+                    // assuming no one has gated the syntax with something like `#[cfg(FALSE)]`.+                    err.delay_as_bug();+                    *self = snapshot;+                    return Ok(None);

I would add another closure or fn can_begin_macro that checks one token for is_ident and two tokens for either :: or !, and only clone if neither are true. That would keep the cost of cloning down for the happy path.

Centril

comment created time in a day

Pull request review commentrust-lang/rust

EXPERIMENT: Recover on stmts/exprs at module level, suggesting to wrap in function

 LL | pub(crate) () fn foo() {}    |    = help: you likely meant to define an item, e.g., `pub(crate) fn foo() {}` -error: expected item, found `(`+error: statements cannot reside in modules   --> $DIR/pub-restricted-error-fn.rs:1:12    | LL | pub(crate) () fn foo() {}-   |            ^ expected item+   |            ^^

This seems less than ideal. I think when we're midway some item head, we should not emit the suggestion.

Centril

comment created time in a day

Pull request review commentrust-lang/rust

EXPERIMENT: Recover on stmts/exprs at module level, suggesting to wrap in function

 impl<'a> Parser<'a> {         } else if vis.node.is_pub() && self.isnt_macro_invocation() {             self.recover_missing_kw_before_item()?;             return Ok(None);-        } else if macros_allowed && self.token.is_path_start() {+        } else if let Some(kind) = if macros_allowed && self.token.is_path_start() {+            self.parse_item_macro(vis, mod_stmt)?+        } else {+            None+        } {             // MACRO INVOCATION ITEM-            (Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?))+            (Ident::invalid(), ItemKind::Mac(kind))         } else {

This doesn't seem right (} else { None } { (...) } else {)

Centril

comment created time in a day

Pull request review commentrust-lang/rust

EXPERIMENT: Recover on stmts/exprs at module level, suggesting to wrap in function

-error: expected item, found `;`+error: statements cannot reside in modules   --> $DIR/issue-49040.rs:1:28    | LL | #![allow(unused_variables)];-   |                            ^ help: remove this semicolon+   |                            ^+   |+   = note: the program entry point starts in `fn main() { ... }`, defined in `main.rs`+   = note: for more on functions and how to structure your program, see https://doc.rust-lang.org/book/ch03-03-how-functions-work.html+help: consider moving the statements into a function+   |+LL | #![allow(unused_variables)]fn my_function() { }+   |                            ^^^^^^^^^^^^^^^^^^^^

This is enough of a regression that it should be accounted for, IMO.

Centril

comment created time in a day

Pull request review commentrust-lang/rust

Accept `Enum::<Param>::Variant {}` over `Enum::Variant::<Param> {}`

 impl<'a, 'hir> LoweringContext<'a, 'hir> {                         Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {                             Some(parent_def_id(self, def_id))                         }-                        Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {-                            Some(parent_def_id(self, def_id))-                        }

Changed it in a backwards compatible way. Now the default behavior will remain the same unless the enum path segment has arguments, and in that case only that one will have the Some(parent_def_id). This keeps the current behavior while also allowing the newer syntax to work correctly.

estebank

comment created time in a day

push eventestebank/rust

Esteban Küber

commit sha aafdbb693eb4a4f7a6f885b75a24a528382ab9b7

Treat `ExprKind::Path` and `ExprKind::Struct` the same for the purposes of path checking

view details

Esteban Küber

commit sha 20d22580ad059b89734388286472fe2d7bf5e0d5

Lint against `E::V::<P>`, suggest `E::<P>::V`

view details

push time in a day

Pull request review commentrust-lang/rust

[Do not merge yet] Treat `ExprKind::Path` and `ExprKind::Struct` the same for the purposes of path checking

 fn in_match() {     let foo = Foo::Bar { field: &y };     //~^ ERROR `y` does not live long enough     match foo {-        Foo::Bar::<'static> { field: _z } => {-        }+        Foo::Bar::<'static> { field: _z } => {}+    }+}++fn in_let_2() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    //~^ ERROR `y` does not live long enough+    let Foo::<'static>::Bar { field: _z } = foo;+}++fn in_match_2() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    //~^ ERROR `y` does not live long enough+    match foo {+        Foo::<'static>::Bar { field: _z } => {}+    }+}++// FIXME: the following seem to be incorrect and would be a regression.+fn in_let_3() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    let Foo::Bar { field: _z } = foo;+}++fn in_match_3() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    match foo {+        Foo::Bar { field: _z } => {}
[DEBUG rustc_mir::borrow_check::renumber] visit_region: region='_#2r
[DEBUG rustc_mir::borrow_check::renumber] visit_region(region=ReErased, location=bb0[7])
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=ReErased)
[DEBUG rustc_mir::borrow_check::renumber] visit_region: region='_#3r
[DEBUG rustc_mir::borrow_check::renumber] visit_substs(substs=[ReStatic], location=bb0[8])
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=[ReStatic])
[DEBUG rustc_mir::borrow_check::renumber] visit_substs: substs=['_#4r]
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=&'static u32)
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=(), ty_context=ReturnTy(SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:38:1: 42:2, scope: scope[0] }))
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=())
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=()
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=(), ty_context=LocalDecl { local: _0, source_info: SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:38:15: 38:15, scope: scope[0] } })
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=())
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=()
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=u32, ty_context=LocalDecl { local: _1, source_info: SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:39:9: 39:10, scope: scope[0] } })
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=u32)
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=u32
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=Foo<'static>, ty_context=LocalDecl { local: _2, source_info: SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:40:9: 40:12, scope: scope[1] } })
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=Foo<'static>)
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=Foo<'_>
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=&'static u32, ty_context=LocalDecl { local: _3, source_info: SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:40:33: 40:35, scope: scope[0] } })
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=&'static u32)
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=&u32

vs before the change

[DEBUG rustc_mir::borrow_check::renumber] visit_region: region='_#2r
[DEBUG rustc_mir::borrow_check::renumber] visit_region(region=ReErased, location=bb0[7])
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=ReErased)
[DEBUG rustc_mir::borrow_check::renumber] visit_region: region='_#3r
[DEBUG rustc_mir::borrow_check::renumber] visit_substs(substs=[ReScope(Remainder { block: 26, first_statement_index: 1})], location=bb0[8])
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=[ReScope(Remainder { block: 26, first_statement_index: 1})])
[DEBUG rustc_mir::borrow_check::renumber] visit_substs: substs=['_#4r]
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=&u32)
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=(), ty_context=ReturnTy(SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:5:1: 10:2, scope: scope[0] }))
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=())
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=()
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=(), ty_context=LocalDecl { local: _0, source_info: SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:5:13: 5:13, scope: scope[0] } })
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=())
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=()
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=u32, ty_context=LocalDecl { local: _1, source_info: SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:6:9: 6:10, scope: scope[0] } })
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=u32)
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=u32
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=Foo<'_>, ty_context=LocalDecl { local: _2, source_info: SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:7:9: 7:12, scope: scope[1] } })
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=Foo<'_>)
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=Foo<'_>
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=&u32, ty_context=LocalDecl { local: _3, source_info: SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:7:33: 7:35, scope: scope[0] } })
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=&u32)
[DEBUG rustc_mir::borrow_check::renumber] visit_ty: ty=&u32
[DEBUG rustc_mir::borrow_check::renumber] visit_ty(ty=&u32, ty_context=LocalDecl { local: _4, source_info: SourceInfo { span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:7:33: 7:35, scope: scope[0] } })
[DEBUG rustc_mir::borrow_check::renumber] renumber_regions(value=&u32)
estebank

comment created time in 4 days

Pull request review commentrust-lang/rust

[Do not merge yet] Treat `ExprKind::Path` and `ExprKind::Struct` the same for the purposes of path checking

 fn in_match() {     let foo = Foo::Bar { field: &y };     //~^ ERROR `y` does not live long enough     match foo {-        Foo::Bar::<'static> { field: _z } => {-        }+        Foo::Bar::<'static> { field: _z } => {}+    }+}++fn in_let_2() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    //~^ ERROR `y` does not live long enough+    let Foo::<'static>::Bar { field: _z } = foo;+}++fn in_match_2() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    //~^ ERROR `y` does not live long enough+    match foo {+        Foo::<'static>::Bar { field: _z } => {}+    }+}++// FIXME: the following seem to be incorrect and would be a regression.+fn in_let_3() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    let Foo::Bar { field: _z } = foo;+}++fn in_match_3() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    match foo {+        Foo::Bar { field: _z } => {}
[DEBUG rustc_mir::borrow_check::type_check] check_user_type_annotations: user_type_annotations=[CanonicalUserTypeAnnotation { user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ pattern_substs_on_brace_enum_variant[317d]::Foo[0]), UserSubsts { substs: [ReStatic], user_self_ty: None }) }, span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:40:15: 40:37, inferred_ty: Foo<'_> }, CanonicalUserTypeAnnotation { user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ pattern_substs_on_brace_enum_variant[317d]::Foo[0]), UserSubsts { substs: [ReStatic], user_self_ty: None }) }, span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:41:9: 41:31, inferred_ty: Foo<'_> }, CanonicalUserTypeAnnotation { user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ pattern_substs_on_brace_enum_variant[317d]::Foo[0]), UserSubsts { substs: [ReStatic], user_self_ty: None }) }, span: src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs:41:9: 41:31, inferred_ty: Foo<'_> }]
estebank

comment created time in 4 days

Pull request review commentrust-lang/rust

[Do not merge yet] Treat `ExprKind::Path` and `ExprKind::Struct` the same for the purposes of path checking

 fn in_match() {     let foo = Foo::Bar { field: &y };     //~^ ERROR `y` does not live long enough     match foo {-        Foo::Bar::<'static> { field: _z } => {-        }+        Foo::Bar::<'static> { field: _z } => {}+    }+}++fn in_let_2() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    //~^ ERROR `y` does not live long enough+    let Foo::<'static>::Bar { field: _z } = foo;+}++fn in_match_2() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    //~^ ERROR `y` does not live long enough+    match foo {+        Foo::<'static>::Bar { field: _z } => {}+    }+}++// FIXME: the following seem to be incorrect and would be a regression.+fn in_let_3() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    let Foo::Bar { field: _z } = foo;+}++fn in_match_3() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    match foo {+        Foo::Bar { field: _z } => {}

CC @matthewjasper: @eddyb mentioned that the "user type annotation" system for MIR borrowck might be needing adjustment for these changes. Could you point me in the right direction?

estebank

comment created time in 4 days

Pull request review commentrust-lang/rust

[Do not merge yet] Treat `ExprKind::Path` and `ExprKind::Struct` the same for the purposes of path checking

 fn in_match() {     let foo = Foo::Bar { field: &y };     //~^ ERROR `y` does not live long enough     match foo {-        Foo::Bar::<'static> { field: _z } => {-        }+        Foo::Bar::<'static> { field: _z } => {}+    }+}++fn in_let_2() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    //~^ ERROR `y` does not live long enough+    let Foo::<'static>::Bar { field: _z } = foo;+}++fn in_match_2() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    //~^ ERROR `y` does not live long enough+    match foo {+        Foo::<'static>::Bar { field: _z } => {}+    }+}++// FIXME: the following seem to be incorrect and would be a regression.+fn in_let_3() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    let Foo::Bar { field: _z } = foo;+}++fn in_match_3() {+    let y = 22;+    let foo = Foo::Bar { field: &y };+    match foo {+        Foo::Bar { field: _z } => {}

This should be passing and it isn't, I'm guessing I need to be using Value where I'm using Type somewhere?

estebank

comment created time in 4 days

PR opened rust-lang/rust

[Do not merge yet] Treat `ExprKind::Path` and `ExprKind::Struct` the same for the purposes of path checking

Fix https://github.com/rust-lang/rust/issues/69356.

r? @petrochenkov @eddyb @Centril

+142 -24

0 comment

7 changed files

pr created time in 4 days

create barnchestebank/rust

branch : variant-path-lt

created branch time in 4 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

-error[E0271]: type mismatch resolving `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]> as std::iter::Iterator>::Item == &_`-  --> $DIR/issue-31173.rs:10:10+error[E0271]: type mismatch resolving `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item == &_`+  --> $DIR/issue-31173.rs:14:10    | LL |         .cloned()    |          ^^^^^^ expected `u8`, found reference    |    = note:   expected type `u8`            found reference `&_` -error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope-  --> $DIR/issue-31173.rs:14:10+error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>` in the current scope+  --> $DIR/issue-31173.rs:18:10    | LL |         .collect();-   |          ^^^^^^^ method not found in `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>`+   |          ^^^^^^^ method not found in `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>`+   | +  ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL+   |+LL | pub struct Cloned<I> {+   | -------------------- doesn't satisfy `_: std::iter::Iterator`+...+LL | pub struct TakeWhile<I, P> {+   | -------------------------- doesn't satisfy `<_ as std::iter::Iterator>::Item = &_`    |    = note: the method `collect` exists but the following trait bounds were not satisfied:-           `&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`-           `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`+           `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` which is required by `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator`+           `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` which is required by `&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator`

I put each in its own line now. I need to implement some deduplication without losing the sort order

estebank

comment created time in 4 days

push eventestebank/rust

Steven Degutis

commit sha ac19dffd1eaea34c3861324c2588f9cb1f1489f5

Updating str.chars docs to mention crates.io. This might spare someone else a little time searching the stdlib for unicode/grapheme support.

view details

Oliver Middleton

commit sha 84f3356e0dffc36f57d9be7902822db5d362e24f

Simplify `Skip::nth` and `Skip::last` implementations The main improvement is to make `last` no longer recursive.

view details

Michael Bradshaw

commit sha 348278a7fd5fd459f555dd763e71e12c23c1661a

Stabilize Once::is_completed

view details

Dylan MacKenzie

commit sha c981d67b509f1ba16c97683ad6dc430429899e49

[!] Use `rustc_inherit_overflow_checks` in `next_power_of_two` I believe the previous code was calling `ops::Add::add` instead of the `+` operator to get this behavior.

view details

Dylan MacKenzie

commit sha 2afa99379d9623e50efd290e609447bdc5059af8

Use bespoke macro instead of `?` inside const fns

view details

Dylan MacKenzie

commit sha 269bf89865536964546242589bb186a8a7e3c566

Make integer power methods const

view details

Dylan MacKenzie

commit sha 7fe5eaf7d8cb23ceb71d8e509be13d20ef836114

Test integer exponentiation in a const context

view details

Esteban Küber

commit sha 683ebc2dec0a5b88eb3eaf146e6855ea299d17b8

On mismatched argument count point at arguments

view details

Dylan MacKenzie

commit sha fc5c2956b11e29f931cec010e3f38461ec4ac309

Impl `GenKill` for old dataflow framework's `GenKillSet` This impl is temporary and will be removed along with the old dataflow framework. It allows us to reuse the transfer function of new dataflow analyses when defining old ones

view details

Dylan MacKenzie

commit sha 7d9dadcccca9efc63f30fa1c9adee00effb860d4

Implement `Maybe{Mut,}BorrowedLocals` analyses

view details

Dylan MacKenzie

commit sha 34783b73bd891a66fb2af613fef7492376fc7c8a

Remove outdated `IndirectlyMutableLocals` `MaybeMutBorrowedLocals` serves the same purpose and has a better name.

view details

Dylan MacKenzie

commit sha 9972502bafab062b06ef04c02c653f1b868937bd

Reenable peek test for indirect mutation analysis This uses the new `MaybeMutBorrowedLocals` pass but we keep the `rustc_peek_indirectly_mutable` since the two are interchangable except when inspecting a local after it has been marked `StorageDead`.

view details

Dylan MacKenzie

commit sha 1d737fb032b762e69e8d809c0e042d45e08b457d

Use `MaybeBorrowedLocals` for generator analyses It should have the same semantics as `HaveBeenBorrowedLocals`

view details

Dylan MacKenzie

commit sha d045a17c4b032a858323f6c9bea698ee2e5920b7

Use `MaybeMutBorrowedLocals` for const-checking

view details

Dylan MacKenzie

commit sha 6f167e9c5f421613ff3de37771b1352cd98dd4f7

Remove ignore and add explanation of indirect mutation peek test

view details

Mazdak Farrokhzad

commit sha cec2a9fad057f71fc640392ba3fa47602aea12f6

macro_legacy_warnings -> error

view details

Eric Huss

commit sha 4810c4712f9edc4c378142ace1b868fc2fd1eeea

Add shared script for linkchecking books.

view details

Matthew Jasper

commit sha cd9f5ff2a1c50a5af94ad1dd1c976f631b9f19a6

Check `Copy` lifetimes bounds when copying from a projection

view details

Matthew Jasper

commit sha ddc25456c5945457ba86cb60994ce9872bd98edd

Check types of statics in MIR typeck

view details

Dylan MacKenzie

commit sha 15a5382ef1115ff11c1357fd21ab4aa12626efee

Rename `MaybeBorrowedLocals` constructors

view details

push time in 4 days

issue openedrust-lang/rust

Possibly incorrect syntax `Enum::<Type, Params>::Variant` allowed since 1.33

A coworker recently identified the following case:

pub enum Foo<'a, T> {
    Struct {},
    Tuple(),
    Unit,
    Usage(&'a T),
}
pub fn main() {
    let foo = Foo::<String>::Unit;
    let foo = Foo::<String>::Tuple();
    let foo = Foo::<String>::Struct {};
}

This used to fail because of the lack of implicit bound T: 'a:

error[E0309]: the parameter type `T` may not live long enough
 --> <source>:5:11
  |
1 | pub enum Foo<'a, T> {
  |                  - help: consider adding an explicit lifetime bound `T: 'a`...
...
5 |     Usage(&'a T),
  |           ^^^^^
  |
note: ...so that the reference type `&'a T` does not outlive the data it points at
 --> <source>:5:11
  |
5 |     Usage(&'a T),
  |           ^^^^^

After fixing that, it complains about the type params:

error[E0109]: type parameters are not allowed on this type
 --> <source>:8:21
  |
8 |     let foo = Foo::<String>::Unit;
  |                     ^^^^^^ type parameter not allowed

error[E0109]: type parameters are not allowed on this type
 --> <source>:9:21
  |
9 |     let foo = Foo::<String>::Tuple();
  |                     ^^^^^^ type parameter not allowed

error[E0109]: type parameters are not allowed on this type
  --> <source>:10:21
   |
10 |     let foo = Foo::<String>::Struct {};
   |                     ^^^^^^ type parameter not allowed

Starting in 1.33, all but the Struct path are accepted:

error[E0110]: lifetime arguments are not allowed on this entity
  --> <source>:10:15
   |
10 |     let foo = Foo::<String>::Struct {};
   |               ^^^^^^^^^^^^^^^^^^^^^ lifetime argument not allowed

error[E0107]: wrong number of lifetime arguments: expected 1, found 0
  --> <source>:10:15
   |
10 |     let foo = Foo::<String>::Struct {};
   |               ^^^^^^^^^^^^^^^^^^^^^ expected 1 lifetime argument

The correct code for this would of course be:

pub enum Foo<'a, T> {
    Struct {},
    Tuple(),
    Unit,
    Usage(&'a T),
}
pub fn main() {
    let foo = Foo::Unit::<String>;
    let foo = Foo::Tuple::<String>();
    let foo = Foo::Struct::<String> {};
}

My questions:

  • Was this change in behavior (accepting some of these paths) intended?
  • If so, was it intended to deny only one of these cases?
  • If this change wasn't intended, should we try to reintroduce it or grandfather it in?

Depending on the answer to those questions, the solution to this ticket could be:

  • Make the compiler accept the let foo = Foo::Struct::<String> {}; case
  • Deny all cases with a suggestion pointing at the right syntax

cc @Centril

created time in 4 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

-error[E0271]: type mismatch resolving `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]> as std::iter::Iterator>::Item == &_`-  --> $DIR/issue-31173.rs:10:10+error[E0271]: type mismatch resolving `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item == &_`+  --> $DIR/issue-31173.rs:14:10    | LL |         .cloned()    |          ^^^^^^ expected `u8`, found reference    |    = note:   expected type `u8`            found reference `&_` -error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope-  --> $DIR/issue-31173.rs:14:10+error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>` in the current scope+  --> $DIR/issue-31173.rs:18:10    | LL |         .collect();-   |          ^^^^^^^ method not found in `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>`+   |          ^^^^^^^ method not found in `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>`+   | +  ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL+   |+LL | pub struct Cloned<I> {+   | -------------------- doesn't satisfy `_: std::iter::Iterator`+...+LL | pub struct TakeWhile<I, P> {+   | -------------------------- doesn't satisfy `<_ as std::iter::Iterator>::Item = &_`    |    = note: the method `collect` exists but the following trait bounds were not satisfied:-           `&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`-           `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`+           `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` which is required by `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator`+           `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` which is required by `&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator`

Right now it is sorted alphabetically which is far less than ideal, but we kind of need it for deduplication.

My horse for a FxSortedHashSet!

estebank

comment created time in 5 days

pull request commentrust-lang/rust

Backport only: avoid ICE on bad placeholder type

The PR points at master, what's the appropriate branch to point to for beta backport?

estebank

comment created time in 5 days

PR opened rust-lang/rust

Backport only: avoid ICE on bad placeholder type

#69148 has a proper fix, but it is too big to backport. This change avoids the ICE by actually emitting an appropriate error. The output will be duplicated in some cases, but that's better than the avoidable ICE.

r? @Centril

+329 -68

0 comment

7 changed files

pr created time in 5 days

create barnchestebank/rust

branch : ice-break-backport-bad-placeholder-type

created branch time in 5 days

pull request commentrust-lang/rust

Account for bounds and asociated items when denying `_`

@Centril @oli-obk is on vacation, could you take a look at this?

estebank

comment created time in 5 days

pull request commentrust-lang/rust

Account for bounds and asociated items when denying `_`

@pnkfelix saw the discussion, sounds fair. There's a very small fix that would cause duplicated output but would never ICE at the cost of the extra verbosity. Should I go ahead and do that?

estebank

comment created time in 5 days

pull request commentrust-lang/rust

On mismatched argument count point at arguments

After https://github.com/rust-lang/rust/pull/69265, @bors r=petrochenkov

estebank

comment created time in 6 days

PR opened rust-lang/rust

Tweak binding lifetime suggestion text

We already have a structured suggestion, but the wording made it seem like that wasn't the case.

Fix #65286. r? @varkor

+62 -61

0 comment

23 changed files

pr created time in 6 days

create barnchestebank/rust

branch : consider-lt

created branch time in 6 days

pull request commentrust-lang/rust

Account for bounds and asociated items when denying `_`

ping

estebank

comment created time in 6 days

issue commentrust-lang/rust

"Consider adding an explicit lifetime bound" doesn't take into account existing bounds

We already supply a structured suggestion in this case that can be applied with VSCode. We don't display the whole suggested code to reduce duplication in the text and to fit the intended flow of the text "add lifetime bound..."/"...so that". Changing it should be easy to do, but do we want to?

varkor

comment created time in 6 days

push eventestebank/rust

Esteban Küber

commit sha c5c78d1c1635429fddb7983934c412d4ef94cdc3

Account for arbitrary self types in E0599

view details

push time in 6 days

pull request commentrust-lang/rust

Add more context to E0599 errors

This PR now accounts for arbitrary self types when reporting E0599, but it doesn't help when the trait definition is not crate local.

The suggestion to constrain type parameters is not as good as I would wish (it should suggest constraining the impl directly), but for newcomers it at least leads them in the right direction (they get hit with a second wave of suggestions that when applied make the code compile).

estebank

comment created time in 6 days

push eventestebank/rust

Esteban Küber

commit sha f49369953120ac32f3103517338e71954c4e5a36

Account for arbitrary self types in E0599

view details

push time in 6 days

issue commentrust-lang/rust

Unhelpful error message when using bad receiver type

Is the following output acceptable?

error[E0599]: no method named `test` found for type parameter `impl Test` in the current scope
 --> file5.rs:8:7
  |
4 |     fn test(self: Pin<&mut Self>);
  |                   -------------- the method might not be found because of this arbitrary self type
...
8 |     t.test()
  |       ^^^^ method not found in `impl Test`
RalfJung

comment created time in 6 days

issue commentrust-lang/rust

Unhelpful error message when using bad receiver type

Triage: we no longer emit the incorrect suggestions.

RalfJung

comment created time in 6 days

issue commentrust-lang/rust

Improve E0599 for missing trait bounds (where clauses)

The current output in the PR looks like this

error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
  --> file5.rs:21:9
   |
1  | struct Foo<T> {
   | -------------
   | |
   | method `bar` not found for this
   | doesn't satisfy `Foo<Inner>: Bar`
...
5  | struct Inner {
   | ------------ doesn't satisfy `Inner: std::clone::Clone`
...
9  | trait Bar {
   | --------- `Bar` defines an item `bar`, perhaps you need to implement it
...
21 |     foo.bar();
   |         ^^^ method not found in `Foo<Inner>`
   |
   = note: the method `bar` exists but the following trait bounds were not satisfied:
           `Inner: std::clone::Clone` which is required by `Foo<Inner>: Bar`
   = help: items from traits can only be used if the trait is implemented and in scope

I'm a bit hesitant about removing spans at this point. It might be true that changing it to the following could be a good idea, but I'm not sure:

error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
  --> file5.rs:21:9
   |
1  | struct Foo<T> {
   | ------------- method `bar` not found for this
...
5  | struct Inner {
   | ------------ doesn't satisfy `Inner: std::clone::Clone`
...
21 |     foo.bar();
   |         ^^^ method not found in `Foo<Inner>`
   |
   = note: the method `bar` exists but the following trait bounds were not satisfied:
           `Inner: std::clone::Clone` which is required by `Foo<Inner>: Bar`
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `bar`, perhaps you need to implement it:
           candidate #1: `Bar`
djc

comment created time in 6 days

push eventestebank/rust

Esteban Küber

commit sha 717e9a2b6cc441abb7240fd3b7e34dd97f974784

Suggest constraining type parameters

view details

push time in 6 days

push eventestebank/rust

Esteban Küber

commit sha 992bdc5113046f125f58906e49df1f45369085be

Tweak wording

view details

push time in 7 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

 error[E0599]: no method named `clone` found for struct `std::boxed::Box<dyn Foo>` in the current scope   --> $DIR/unique-object-noncopyable.rs:24:16    |+LL | trait Foo {+   | ---------+   | |+   | doesn't satisfy `dyn Foo: std::clone::Clone`+   | doesn't satisfy `dyn Foo: std::marker::Sized`

We could suggest trait Foo: Clone +Sized 🤔

estebank

comment created time in 7 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

 error[E0599]: no associated item named `ID` found for type `i32` in the current scope   --> $DIR/associated-const-no-item.rs:5:23    |+LL | trait Foo {+   | --------- `Foo` defines an item `ID`+... LL | const X: i32 = <i32>::ID;    |                       ^^ associated item not found in `i32`    |    = help: items from traits can only be used if the trait is implemented and in scope-   = note: the following trait defines an item `ID`, perhaps you need to implement it:-           candidate #1: `Foo`

TODO: we should determine whether the implementing trait is in scope. If it isn't, suggest importing it. If it is, check whether the found adt implements it directly but the bounds weren't fulfilled. If not, suggest implementing it.

estebank

comment created time in 7 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

 impl<'a, 'tcx> ProbeContext<'a, 'tcx> {                             // `potentially_unsatisfied_predicates`.                             return ProbeResult::NoMatch;                         } else {-                            // Some nested subobligation of this predicate-                            // failed.-                            //-                            // FIXME: try to find the exact nested subobligation-                            // and point at it rather than reporting the entire-                            // trait-ref?-                            result = ProbeResult::NoMatch;-                            let trait_ref = self.resolve_vars_if_possible(&trait_ref);-                            possibly_unsatisfied_predicates.push(trait_ref);+                            self.probe(|_| {

To clarify, the changes only affect diagnostic output. possibly_unsatisfied_predicates isn't used for anything else.

estebank

comment created time in 7 days

push eventestebank/rust

Esteban Küber

commit sha 8a6ed32767d18381447ad6c9fa0155fe5e2a57f1

Show information of chain of bound obligations When the obligation that couldn't be fulfilled is specific to a nested obligation, maintain both the nested and parent obligations around for more accurate and detailed error reporting.

view details

Esteban Küber

commit sha ddf3acb37d75c036c7a2b6822bf0fb3cce420c07

Point at closure definitions

view details

Esteban Küber

commit sha 8bd85b045031a4cb6f259dec1c5b0c69f5811c4c

Mention the full path of the implementing trait

view details

push time in 7 days

issue commentrust-lang/rust

"note: method exists but trait bounds not satisfied" could be better

For the original case, would the following output be acceptable?

error[E0599]: no method named `join` found for struct `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:18:18: 18:41]>` in the current scope
  --> file5.rs:18:43
   |
1  | pub trait JoinWithString {
   | ------------------------ this trait defines an item `join`
...
18 |     a.iter().map(|x| x.to_str().unwrap()).join(":");
   |                                           ^^^^ method not found in `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:18:18: 18:41]>`
   |
   = note: the method `join` exists but the following trait bounds were not satisfied:
           `&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:18:18: 18:41]>: std::iter::Iterator`
           `<&mut std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:18:18: 18:41]> as std::iter::Iterator>::Item = std::string::String`
           `<&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:18:18: 18:41]> as std::iter::Iterator>::Item = std::string::String`
           `<std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:18:18: 18:41]> as std::iter::Iterator>::Item = std::string::String`
   = help: items from traits can only be used if the trait is implemented and in scope

That's the current output in #69255. I think I can change it slightly to be less verbose, but worry about it being more confusing in the general case:

error[E0599]: no method named `join` found for struct `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:18:18: 18:41]>` in the current scope
  --> file5.rs:18:43
   |
1  | pub trait JoinWithString {
   | ------------------------ this trait defines an item `join`
...
18 |     a.iter().map(|x| x.to_str().unwrap()).join(":");
   |                                           ^^^^ method not found in `std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:18:18: 18:41]>`
   |
   = note: the method `join` exists but the following trait bounds were not satisfied:
           `&std::iter::Map<std::slice::Iter<'_, std::path::PathBuf>, [closure@file5.rs:18:18: 18:41]>: std::iter::Iterator`
           `<&mut _ as std::iter::Iterator>::Item = std::string::String`
           `<&_ as std::iter::Iterator>::Item = std::string::String`
           `<_ as std::iter::Iterator>::Item = std::string::String`
   = help: items from traits can only be used if the trait is implemented and in scope

The case in the last comment would now be:

error[E0599]: no method named `do_b` found for struct `Example` in the current scope
  --> file5.rs:28:7
   |
1  | pub struct Example;
   | -------------------
   | |
   | method `do_b` not found for this
   | doesn't satisfy `Example: Empty`
...
7  | trait B {
   | ------- this trait defines an item `do_b`
...
28 |     e.do_b();
   |       ^^^^ method not found in `Example`
   |
   = note: the method `do_b` exists but the following trait bounds were not satisfied:
           `Example: Empty`
   = help: items from traits can only be used if the trait is implemented and in scope
durka

comment created time in 7 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {                 }                  if !unsatisfied_predicates.is_empty() {+                    let mut bound_spans = vec![];                     let mut bound_list = unsatisfied_predicates                         .iter()-                        .map(|p| format!("`{} : {}`", p.self_ty(), p.print_only_trait_path()))+                        .filter_map(|p| {+                            let self_ty = p.self_ty();+                            match &self_ty.kind {+                                ty::Adt(def, _) => {+                                    bound_spans.push((+                                        self.tcx+                                            .sess+                                            .source_map()+                                            .def_span(self.tcx.def_span(def.did)),+                                        format!(+                                            "the method `{}` exists but this type doesn't satisfy \+                                             the bound `{}: {}`",+                                            item_name,+                                            p.self_ty(),+                                            p.print_only_trait_path()+                                        ),+                                    ));+                                    None+                                }+                                ty::Dynamic(preds, _) => {+                                    for pred in *preds.skip_binder() {+                                        match pred {+                                            ty::ExistentialPredicate::Trait(tr) => bound_spans+                                                .push((+                                                    self.tcx+                                                        .sess+                                                        .source_map()+                                                        .def_span(self.tcx.def_span(tr.def_id)),+                                                    format!(+                                                        "the method `{}` exists but this trait \

Changed the output in a way that it no longer mentions trait object type.

estebank

comment created time in 7 days

push eventestebank/rust

Esteban Küber

commit sha 41cfabc8e3b26c3598482c27146798bf93ac1889

Track all predicates in errors, not just trait obligations Surface associated type projection bounds that could not be fulfilled in E0599 errors. Always present the list of unfulfilled trait bounds, regardless of whether we're pointing at the ADT or trait that didn't satisfy it.

view details

push time in 7 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

+// FIXME: missing sysroot spans (#53081)+// ignore-i586-unknown-linux-gnu+// ignore-i586-unknown-linux-musl+// ignore-i686-unknown-linux-musl

At least we're tracking the underlying issue now :o)

estebank

comment created time in 7 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

 impl<'a, 'tcx> ProbeContext<'a, 'tcx> {                             // `potentially_unsatisfied_predicates`.                             return ProbeResult::NoMatch;                         } else {-                            // Some nested subobligation of this predicate-                            // failed.-                            //-                            // FIXME: try to find the exact nested subobligation-                            // and point at it rather than reporting the entire-                            // trait-ref?-                            result = ProbeResult::NoMatch;-                            let trait_ref = self.resolve_vars_if_possible(&trait_ref);-                            possibly_unsatisfied_predicates.push(trait_ref);+                            self.probe(|_| {

There are no functional issues. If there's a mix of trait and projection predicates, and the underlying divergence is due to a projection the output is not as clear as it should be, but I am working on expanding it.

estebank

comment created time in 7 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {                 }                  if !unsatisfied_predicates.is_empty() {+                    let mut bound_spans = vec![];                     let mut bound_list = unsatisfied_predicates                         .iter()-                        .map(|p| format!("`{} : {}`", p.self_ty(), p.print_only_trait_path()))+                        .filter_map(|p| {+                            let self_ty = p.self_ty();+                            match &self_ty.kind {+                                ty::Adt(def, _) => {+                                    bound_spans.push((+                                        self.tcx+                                            .sess+                                            .source_map()+                                            .def_span(self.tcx.def_span(def.did)),+                                        format!(+                                            "the method `{}` exists but this type doesn't satisfy \+                                             the bound `{}: {}`",+                                            item_name,+                                            p.self_ty(),+                                            p.print_only_trait_path()+                                        ),+                                    ));+                                    None+                                }+                                ty::Dynamic(preds, _) => {+                                    for pred in *preds.skip_binder() {+                                        match pred {+                                            ty::ExistentialPredicate::Trait(tr) => bound_spans+                                                .push((+                                                    self.tcx+                                                        .sess+                                                        .source_map()+                                                        .def_span(self.tcx.def_span(tr.def_id)),+                                                    format!(+                                                        "the method `{}` exists but this trait \

Correct. I wanted to push out the PR asap for feedback, but the wording is still in flux. I wanted to verify I could get all the pieces in place first.

estebank

comment created time in 7 days

issue commentrust-lang/rust

Bad error message with async main

@Nokel81 could you push your code to a branch we can look at and comment inline? You should be extracting an existing span.

Nokel81

comment created time in 7 days

push eventestebank/rust

Esteban Küber

commit sha 1930b41fb95b4542597ff7100f13ca7a08d0929a

On single local candidate, use span label

view details

Esteban Küber

commit sha 1e353d603cd3a2bc29e52c8d0b392ab5ca57a7a7

Deduplicate information in E0599

view details

push time in 8 days

issue commentrust-lang/rust

Improve E0599 for missing trait bounds (where clauses)

What about this?

error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
  --> file5.rs:24:9
   |
1  | struct Foo<T> {
   | ------------- method `bar` not found for this
...
5  | struct Inner {
   | ------------ the method `bar` but this type doesn't satisfy the bound `Inner: std::clone::Clone`
...
9  | trait Bar {
   | --------- this trait defines an item `bar`
...
24 |     foo.bar();
   |         ^^^ method not found in `Foo<Inner>`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
djc

comment created time in 8 days

issue commentrust-lang/rust

Cannot use `use Self::*;` inside a method

It depends on how we close this ticket: if we extend the language to allow Self, then the lang team should chime in. If we continue to deny it rustc should suggest using A instead of Self here. For the later you can go ahead and implement it directly without much fuzz (and likely it would be 90% of the machinery to implement the actual lang feature). For the former, you could make the argument that this falls under the existing RFC (although there's no direct mention about this, one way or another).

varkor

comment created time in 8 days

issue commentrust-lang/rust

'index out of bounds: the len is 1 but the index is 1': libcore/slice/mod.rs

@hellow554 I'm 99% sure it will.

harrisonthorne

comment created time in 8 days

issue commentrust-lang/rust

Improve E0599 for missing trait bounds (where clauses)

What do you think of the following output?

error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
  --> file5.rs:21:9
   |
1  | struct Foo<T> {
   | ------------- method `bar` not found for this
...
5  | struct Inner {
   | ------------ this type doesn't satisfy the bound `std::clone::Clone`
...
21 |     foo.bar();
   |         ^^^ method not found in `Foo<Inner>`
   |
   = note: the method `bar` exists but the following trait bounds were not satisfied:
           `Inner: std::clone::Clone`
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `bar`, perhaps you need to implement it:
           candidate #1: `Bar`

Screen Shot 2020-02-18 at 12 05 00 AM

I'll look into removing the last few lines as I agree that they are somewhat misleading here and obscure the solution, but we have to make sure we don't actually hide information useful for other cases with different underlying problems.

djc

comment created time in 8 days

push eventestebank/rust

Esteban Küber

commit sha 9f63be0e85e26043684d9dd14e493d41f22578d6

Reduce vebosity of E0599

view details

push time in 8 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

 impl<'a, 'tcx> ProbeContext<'a, 'tcx> {                             // `potentially_unsatisfied_predicates`.                             return ProbeResult::NoMatch;                         } else {-                            // Some nested subobligation of this predicate-                            // failed.-                            //-                            // FIXME: try to find the exact nested subobligation-                            // and point at it rather than reporting the entire-                            // trait-ref?-                            result = ProbeResult::NoMatch;-                            let trait_ref = self.resolve_vars_if_possible(&trait_ref);-                            possibly_unsatisfied_predicates.push(trait_ref);+                            self.probe(|_| {+                                match self.select_trait_candidate(trait_ref) {+                                    Ok(Some(traits::VtableImpl(traits::VtableImplData {+                                        nested,+                                        ..+                                    }))) if !nested.is_empty() => {+                                        for obligation in nested {+                                            // Determine exactly which obligation wasn't met, so+                                            // that we can give more context in the error.+                                            if !self.predicate_may_hold(&obligation) {+                                                result = ProbeResult::NoMatch;+                                                if let Some(poly_trait_ref) =+                                                    obligation.predicate.to_opt_poly_trait_ref()+                                                {+                                                    let trait_ref = poly_trait_ref.clone();+                                                    let trait_ref = trait_ref.skip_binder();+                                                    possibly_unsatisfied_predicates+                                                        .push(*trait_ref);+                                                }+                                            }+                                        }+                                    }+                                    _ => {}+                                }+                                // Some nested subobligation of this predicate+                                // failed.+                                //+                                // FIXME: try to find the exact nested subobligation+                                // and point at it rather than reporting the entire+                                // trait-ref?+                                result = ProbeResult::NoMatch;+                                let trait_ref = self.resolve_vars_if_possible(&trait_ref);+                                possibly_unsatisfied_predicates.push(trait_ref);

Pushed a new commit with this change. Please contrast the delta between the two commits to decide which version we should go with.

estebank

comment created time in 8 days

push eventestebank/rust

Esteban Küber

commit sha 2a5452b27baa428bc4b27dbecf224e9a295d7c9f

Reduce vebosity of E0599

view details

push time in 8 days

issue commentrust-lang/rust

Trait bound is ignored

Should we close the duplicates?

Maybe, but let's make sure we link them up.

And also this issue, given that we no longer suggest wrong?

No, we need to improve the output when dealing with arbitrary self types. The current output is at least no longer wrong but it is misleading and actively confusing for anyone not intimately knowledgeable about the language.

fuchsnj

comment created time in 8 days

Pull request review commentrust-lang/rust

Add more context to E0599 errors

 impl<'a, 'tcx> ProbeContext<'a, 'tcx> {                             // `potentially_unsatisfied_predicates`.                             return ProbeResult::NoMatch;                         } else {-                            // Some nested subobligation of this predicate-                            // failed.-                            //-                            // FIXME: try to find the exact nested subobligation-                            // and point at it rather than reporting the entire-                            // trait-ref?-                            result = ProbeResult::NoMatch;-                            let trait_ref = self.resolve_vars_if_possible(&trait_ref);-                            possibly_unsatisfied_predicates.push(trait_ref);+                            self.probe(|_| {+                                match self.select_trait_candidate(trait_ref) {+                                    Ok(Some(traits::VtableImpl(traits::VtableImplData {+                                        nested,+                                        ..+                                    }))) if !nested.is_empty() => {+                                        for obligation in nested {+                                            // Determine exactly which obligation wasn't met, so+                                            // that we can give more context in the error.+                                            if !self.predicate_may_hold(&obligation) {+                                                result = ProbeResult::NoMatch;+                                                if let Some(poly_trait_ref) =+                                                    obligation.predicate.to_opt_poly_trait_ref()+                                                {+                                                    let trait_ref = poly_trait_ref.clone();+                                                    let trait_ref = trait_ref.skip_binder();+                                                    possibly_unsatisfied_predicates+                                                        .push(*trait_ref);+                                                }+                                            }+                                        }+                                    }+                                    _ => {}+                                }+                                // Some nested subobligation of this predicate+                                // failed.+                                //+                                // FIXME: try to find the exact nested subobligation+                                // and point at it rather than reporting the entire+                                // trait-ref?+                                result = ProbeResult::NoMatch;+                                let trait_ref = self.resolve_vars_if_possible(&trait_ref);+                                possibly_unsatisfied_predicates.push(trait_ref);

This can alternatively be in the _ => {} branch above instead, and that will reduce the verbosity of the errors below. I wasn't sure if that increases or decreases the readability of the errors.

estebank

comment created time in 8 days

PR opened rust-lang/rust

Add more context to E0599 errors

Point at the intermediary unfulfilled trait bounds.

Fix #52523, fix #61661, cc #36513.

+203 -56

0 comment

27 changed files

pr created time in 8 days

create barnchestebank/rust

branch : e0599-details

created branch time in 8 days

issue commentrust-lang/rust

Improve E0599 for missing trait bounds (where clauses)

Would the following be enough of an improvement?

error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
   --> file5.rs:21:9
    |
1   |   struct Foo<T> {
    |   ------------- method `bar` not found for this
...
21  |       foo.bar();
    |           ^^^ method not found in `Foo<Inner>`
    |
    = note: the method `bar` exists but the following trait bounds were not satisfied:
            `Inner: std::clone::Clone`
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `bar`, perhaps you need to implement it:
            candidate #1: `Bar`
djc

comment created time in 8 days

issue commentrust-lang/rust

Compiler should not omit associated type in compile error message

Associated items are predicates that are not carried around in the type, so by the time reach this we're not ferrying around the assoc types anymore. This will be hard to fix but very worthwhile.

rhysd

comment created time in 8 days

pull request commentrust-lang/rust

Add an early-exit to `overlapping_impls`

@bors r- as it needs a rebase.

jonas-schievink

comment created time in 8 days

pull request commentrust-lang/rust

Add an early-exit to `overlapping_impls`

I am slightly worried about the mild regressions, but syn actually improved.

@rust-lang/compiler Let's keep an eye out for this in case there are more regressions in the wild, but I believe that this should have a net positive impact.

@bors r+ rollup=never

jonas-schievink

comment created time in 8 days

Pull request review commentrust-lang/rust

On privacy error caused by private reexport, use spans to show the `use` chain

 error[E0603]: struct import `ParseOptions` is private LL | pub use parser::ParseOptions;    |                 ^^^^^^^^^^^^ this struct import is private    |-note: the struct import `ParseOptions` is defined here+note: the used restricted re-export of `ParseOptions`...   --> $DIR/issue-55884-2.rs:9:9    | LL |     use ParseOptions;    |         ^^^^^^^^^^^^+note: ...through this public re-export of `ParseOptions`...+  --> $DIR/issue-55884-2.rs:12:9+   |+LL | pub use parser::ParseOptions;+   |         ^^^^^^^^^^^^^^^^^^^^+note: ...through this public re-export of `ParseOptions`+  --> $DIR/issue-55884-2.rs:6:13+   |+LL |     pub use options::*;+   |             ^^^^^^^^^^

I think this clarification in particular will be incredibly useful when trying to understand these errors.

estebank

comment created time in 8 days

pull request commentrust-lang/rust

On privacy error caused by private reexport, use spans to show the `use` chain

@Dylan-DPC thanks for the ping.

@petrochenkov rebased and squashed on top of latest master, the diff is much smaller now.

estebank

comment created time in 8 days

push eventestebank/rust

bors

commit sha 698fcd38fa9548e64a2092ff48c9d15ceb57d40c

Auto merge of #68545 - estebank:verbose-bound-display, r=petrochenkov Use better bound names in `-Zverbose` mode r? @petrochenkov as per https://github.com/rust-lang/rust/pull/67951/files#r365524015

view details

Eduard-Mihai Burtescu

commit sha 787c458eeb20e447989124e2900e02e8e03b1c51

Don't use ExpnKind::descr to get the name of a bang macro.

view details

Eduard-Mihai Burtescu

commit sha a7b0aa0675f6e81bdb62e614c020a6862381c98a

rustc_span: move pretty syntax from macro_backtrace to ExpnKind::descr.

view details

Eduard-Mihai Burtescu

commit sha 75284f8cbdfa17046156528dc3aa5303f8752f97

rustc_span: replace MacroBacktrace with ExpnData.

view details

Eduard-Mihai Burtescu

commit sha 6980f82c0d152446506fee4d4a45d8afdf4ad9a4

rustc_span: return an impl Iterator instead of a Vec from macro_backtrace.

view details

Guillaume Gomez

commit sha 85079f8b1fa8291593735b9b577e8e0dc22ad3b6

Fix run button positionning in case of scrolling

view details

Esteban Küber

commit sha 697fdc568e28fbb376567eda4edb2c2a05db68de

Suggest defining type parameter when appropriate ``` error[E0412]: cannot find type `T` in this scope --> file.rs:3:12 | 3 | impl Trait<T> for Struct {} | - ^ not found in this scope | | | help: you might be missing a type parameter: `<T>` ``` Fix #64298.

view details

Andreas Molzer

commit sha 47ae565ed4f1b2a7cc754d4cf0af520b5e6841b9

Add a method to query the capacity of a BufWriter

view details

bors

commit sha a237641c7df8125b89b8f9c2a3594964ba8188f8

Auto merge of #68407 - eddyb:iter-macro-backtrace, r=petrochenkov rustc_span: return an impl Iterator instead of a Vec from macro_backtrace. Having `Span::macro_backtrace` produce an `impl Iterator<Item = ExpnData>` allows #67359 to use it instead of rolling its own similar functionality. The move from `MacroBacktrace` to `ExpnData` (which the first two commits are prerequisites for) both eliminates unnecessary allocations, and is strictly more flexible (exposes more information). r? @petrochenkov

view details

Oliver Middleton

commit sha bbc2ae7590ad53fca02fda187e7f9c2470c9e949

rustdoc: Fix re-exporting primitive types * Generate links to the primitive type docs for re-exports. * Don't ICE on cross crate primitive type re-exports. * Make primitive type re-exports show up cross crate.

view details

Tomasz Miąsko

commit sha a6137fb730d59141ff2f5744b6cf36e29ef74e94

compiletest: Remove unnecessary memory allocation in iter_header Replace `BufRead::lines` with `BuRead::read_line` to reduce memory allocations.

view details

Tomasz Miąsko

commit sha 5ebec91abbfdbf6040918cb797765550812a03fd

compiletest: Parse EarlyProps from a reader

view details

Tomasz Miąsko

commit sha bb6aac38131528384343e6724578a89bf8daf68f

compiletest: Update mode list displayed in `--help`

view details

Tomasz Miąsko

commit sha d857f6f1aba6308cb4458ec1d210f722d55017cb

compiletest: Add unit tests for EarlyProps

view details

Tomasz Miąsko

commit sha 9a154a94b30baa333fe7399ee6dc2a01f395a27d

compiletest: Remove unused llvm-cxxflags option

view details

Tomasz Miąsko

commit sha db7ee9534522196a9e750833c0303d8275c683bc

compiletest: Derive Default for EarlyProps

view details

Tomasz Miąsko

commit sha 3c02afe965a2dcfecd42e27bb225f9d2af68e838

compiletest: Don't load TestProps from a directories

view details

Tomasz Miąsko

commit sha 08a1c566a792dcf9657d293155f7ada87746bb65

Detect use-after-scope bugs with AddressSanitizer Enable use-after-scope checks by default when using AddressSanitizer. They allow to detect incorrect use of stack objects after their scope have already ended. The detection is based on LLVM lifetime intrinsics. To facilitate the use of this functionality, the lifetime intrinsics are now emitted regardless of optimization level if enabled sanitizer makes use of them.

view details

Tomasz Miąsko

commit sha 461aada2fe0f1305b99b527b1b5ff8696a3e9ccc

Add use after scope example to the unstable book

view details

Tomasz Miąsko

commit sha 47fd27a637b7311c81437f138932ddb426350ab7

Move sanitizer tests to a separate directory

view details

push time in 8 days

Pull request review commentrust-lang/rust

Implement RFC 2532 – Associated Type Defaults

-You implemented a trait, overriding one or more of its associated types but did

I believe the common action is to have a title "Note: this error code is no longer emitted by the compiler." at the top and ignore the code samples: https://doc.rust-lang.org/error-index.html

jonas-schievink

comment created time in 8 days

Pull request review commentrust-lang/rust

Implement RFC 2532 – Associated Type Defaults

-You implemented a trait, overriding one or more of its associated types but did

Shouldn't this file be left alone with a note mentioning that it is no longer emitted?

jonas-schievink

comment created time in 8 days

issue commentrust-lang/rust

Trait bound is ignored

Current output, we no longer provide the incorrect suggestions:

error[E0599]: no method named `poll_next` found for type parameter `T` in the current scope
  --> src/lib.rs:14:23
   |
14 |         self.upstream.poll_next()
   |                       ^^^^^^^^^ method not found in `T`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait

This is another case of #69069.

fuchsnj

comment created time in 8 days

issue commentrust-lang/rust

arbitrary self types causes unexpected error messages

Cc https://github.com/rust-lang/rust/issues/66289

nikomatsakis

comment created time in 8 days

pull request commentrust-lang/rust

Canonicalize path when displaying a `FileName::Real`

I think you'd need to modify src/test/run-make-fulldeps/libtest-json/Makefile to invoke rustc in a way that will normalize the path (which I'm not sure is possible for this output) or to replace the full path with a normalized path yourself in the Makefile.

LeSeulArtichaut

comment created time in 8 days

Pull request review commentrust-lang/rust

Parse & reject postfix operators after casts

+// edition:2018+#![crate_type = "lib"]+#![feature(type_ascription)]+use std::future::Future;+use std::pin::Pin;++// This tests the parser for "x as Y[z]". It errors, but we want to give useful+// errors and parse such that further code gives useful errors.+pub fn index_after_as_cast() {+    vec![1, 2, 3] as Vec<i32>[0];+    //~^ ERROR: casts cannot be followed by indexing+    vec![1, 2, 3]: Vec<i32>[0];+    //~^ ERROR: casts cannot be followed by indexing+}++pub fn index_after_cast_to_index() {+    (&[0]) as &[i32][0];+    //~^ ERROR: casts cannot be followed by indexing+    (&[0i32]): &[i32; 1][0];+    //~^ ERROR: casts cannot be followed by indexing+}++pub fn cast_after_cast() {+    if 5u64 as i32 as u16 == 0u16 {++    }+    if 5u64: u64: u64 == 0u64 {++    }+    let _ = 5u64: u64: u64 as u8 as i8 == 9i8;+    let _ = 0i32: i32: i32;+    let _ = 0 as i32: i32;+    let _ = 0i32: i32 as i32;+    let _ = 0 as i32 as i32;+    let _ = 0i32: i32: i32 as u32 as i32;

Should we also have these tests with trailing method calls?

daboross

comment created time in 8 days

more