Question:
This affects the test suites for the and crates.
triage: I-wrong, P-high (1.0)
triage: P-high (1.0)
I ended up adding the 1.0 milestone by hand; isn't the above note with supposed to do it?
cc
the log above says that highfive did add this to the 1.0 milestone - it might just have been that your local view of the webpage needed refreshing?
yeah I guess so, I don't know what happened anymore. Maybe I should have given highfive a little more time to react.

ast::ExprUnary(ast::UnNot, ref inner) => { match try!(eval_const_expr_partial(tcx, &**inner, ety)) { const_int(i) => const_int(!i), <del> const_uint(i) => const_uint(!i), </del> <ins> const_uint(i) => const_uint_not(i, expr_uint_type), </ins> const_bool(b) => const_bool(!b), const_str(_) => signal!(e, NotOnString), const_float(_) => signal!(e, NotOnFloat),


Question:
This affects the test suites for the and crates.
triage: I-wrong, P-high (1.0)
triage: P-high (1.0)
I ended up adding the 1.0 milestone by hand; isn't the above note with supposed to do it?
cc
the log above says that highfive did add this to the 1.0 milestone - it might just have been that your local view of the webpage needed refreshing?
yeah I guess so, I don't know what happened anymore. Maybe I should have given highfive a little more time to react.

<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. const U8_MAX_HALF: u8 = !0u8 / 2; const U16_MAX_HALF: u16 = !0u16 / 2; const U32_MAX_HALF: u32 = !0u32 / 2; const U64_MAX_HALF: u64 = !0u64 / 2; fn main() { assert_eq!(U8_MAX_HALF, 0x7f); assert_eq!(U16_MAX_HALF, 0x7fff); assert_eq!(U32_MAX_HALF, 0x7fff_ffff); assert_eq!(U64_MAX_HALF, 0x7fff_ffff_ffff_ffff); } </ins>


Question:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim

let mut where_predicates = where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect::<Vec<_>>(); <del> // Type parameters have a Sized bound by default unless removed with // ?Sized. Scan through the predicates and mark any type parameter with // a Sized bound, removing the bounds as we find them. </del> <ins> // In the surface language, all type parameters except `Self` have an // implicit `Sized` bound unless removed with `?Sized`. // However, in the list of where-predicates below, `Sized` appears like a // normal bound: It's either present (the type is sized) or // absent (the type is unsized) but never *maybe* (i.e. `?Sized`). </ins> // <del> // Note that associated types also have a sized bound by default, but we </del> <ins> // This is unsuitable for rendering. // Thus, as a first step remove all `Sized` bounds that should be implicit. // // Note that associated types also have an implicit `Sized` bound but we </ins> // don't actually know the set of associated types right here so that's <del> // handled in cleaning associated types </del> <ins> // handled when cleaning associated types. </ins> let mut sized_params = FxHashSet::default(); <del> where_predicates.retain(|pred| match *pred { WherePredicate::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => { if bounds.iter().any(|b| b.is_sized_bound(cx)) { sized_params.insert(*g); false } else { true } </del> <ins> where_predicates.retain(|pred| { if let WherePredicate::BoundPredicate { ty: Generic(g), bounds, .. } = pred && *g != kw::SelfUpper && bounds.iter().any(|b| b.is_sized_bound(cx)) { sized_params.insert(*g); false } else { true </ins> } <del> _ => true, </del> }); <del> // Run through the type parameters again and insert a ?Sized // unbound for any we didn't find to be Sized. </del> <ins> // As a final step, go through the type parameters again and insert a // `?Sized` bound for each one we didn't find to be `Sized`. </ins> for tp in &stripped_params { <del> if matches!(tp.kind, types::GenericParamDefKind::Type { .. }) && !sized_params.contains(&tp.name) </del> <ins> if let types::GenericParamDefKind::Type { .. } = tp.kind && !sized_params.contains(&tp.name) </ins> { where_predicates.push(WherePredicate::BoundPredicate { ty: Type::Generic(tp.name),


Question:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim

<ins> #![crate_type = "lib"] pub trait U/*: ?Sized */ { fn modified(self) -> Self where Self: Sized { self } fn touch(&self)/* where Self: ?Sized */{} } pub trait S: Sized {} </ins>


Question:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim

fn touch(&self)
   No newline at end of file


Question:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim

<ins> #![crate_type = "lib"] #![crate_name = "usr"] // aux-crate:issue_24183=issue-24183.rs // edition: 2021 // @has usr/trait.U.html // @has - '//*[@class="item-decl"]' "pub trait U {" // @has - '//*[@id="method.modified"]'  // "fn modified(self) -> Self // where  //     Self: Sized" // @snapshot method_no_where_self_sized - '//*[@id="method.touch"]/*[@class="code-header"]' pub use issue_24183::U; // @has usr/trait.S.html // @has - '//*[@class="item-decl"]' 'pub trait S: Sized {' pub use issue_24183::S; </ins>


Question:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim

AutoTraitFinder { cx } } <ins> fn generate_for_trait( &mut self, ty: Ty<'tcx>, trait_def_id: DefId, param_env: ty::ParamEnv<'tcx>, param_env_def_id: DefId, f: &auto_trait::AutoTraitFinder<'tcx>, // If this is set, show only negative trait implementations, not positive ones. discard_positive_impl: bool, ) -> Option<Item> { let tcx = self.cx.tcx; let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) }; if !self.cx.generated_synthetics.borrow_mut().insert((ty, trait_def_id)) { debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref); return None; } let result = f.find_auto_trait_generics(ty, param_env, trait_def_id, |infcx, info| { let region_data = info.region_data; let names_map = tcx .generics_of(param_env_def_id) .params .iter() .filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => Some(param.name), _ => None, }) .map(|name| (name, Lifetime(name))) .collect(); let lifetime_predicates = Self::handle_lifetimes(&region_data, &names_map); let new_generics = self.param_env_to_generics( infcx.tcx, param_env_def_id, info.full_user_env, lifetime_predicates, info.vid_to_region, ); debug!( "find_auto_trait_generics(param_env_def_id={:?}, trait_def_id={:?}):  finished with {:?}", param_env_def_id, trait_def_id, new_generics ); new_generics }); let negative_polarity; let new_generics = match result { AutoTraitResult::PositiveImpl(new_generics) => { negative_polarity = false; if discard_positive_impl { return None; } new_generics } AutoTraitResult::NegativeImpl => { negative_polarity = true; // For negative impls, we use the generic params, but *not* the predicates, // from the original type. Otherwise, the displayed impl appears to be a // conditional negative impl, when it's really unconditional. // // For example, consider the struct Foo<T: Copy>(*mut T). Using // the original predicates in our impl would cause us to generate // `impl !Send for Foo<T: Copy>`, which makes it appear that Foo // implements Send where T is not copy. // // Instead, we generate `impl !Send for Foo<T>`, which better // expresses the fact that `Foo<T>` never implements `Send`, // regardless of the choice of `T`. let params = (tcx.generics_of(param_env_def_id), ty::GenericPredicates::default()) .clean(self.cx) .params; Generics { params, where_predicates: Vec::new() } } AutoTraitResult::ExplicitImpl => return None, }; Some(Item { source: Span::dummy(), name: None, attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(param_env_def_id.krate), kind: box ImplItem(Impl { unsafety: hir::Unsafety::Normal, generics: new_generics, provided_trait_methods: Default::default(), trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), for_: ty.clean(self.cx), items: Vec::new(), negative_polarity, synthetic: true, blanket_impl: None, }), }) } </ins> // FIXME(eddyb) figure out a better way to pass information about // parametrization of `ty` than `param_env_def_id`. crate fn get_auto_trait_impls(&mut self, ty: Ty<'tcx>, param_env_def_id: DefId) -> Vec<Item> {


Question:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim

debug!("get_auto_trait_impls({:?})", ty); let auto_traits: Vec<_> = self.cx.auto_traits.iter().cloned().collect(); <del> auto_traits </del> <ins> let mut auto_traits: Vec<Item> = auto_traits </ins> .into_iter() .filter_map(|trait_def_id| { <del> let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) }; if !self.cx.generated_synthetics.borrow_mut().insert((ty, trait_def_id)) { debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref); return None; } let result = f.find_auto_trait_generics(ty, param_env, trait_def_id, |infcx, info| { let region_data = info.region_data; let names_map = tcx .generics_of(param_env_def_id) .params .iter() .filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => Some(param.name), _ => None, }) .map(|name| (name, Lifetime(name))) .collect(); let lifetime_predicates = Self::handle_lifetimes(&region_data, &names_map); let new_generics = self.param_env_to_generics( infcx.tcx, param_env_def_id, info.full_user_env, lifetime_predicates, info.vid_to_region, ); debug!( "find_auto_trait_generics(param_env_def_id={:?}, trait_def_id={:?}):  finished with {:?}", param_env_def_id, trait_def_id, new_generics ); new_generics }); let negative_polarity; let new_generics = match result { AutoTraitResult::PositiveImpl(new_generics) => { negative_polarity = false; new_generics } AutoTraitResult::NegativeImpl => { negative_polarity = true; // For negative impls, we use the generic params, but *not* the predicates, // from the original type. Otherwise, the displayed impl appears to be a // conditional negative impl, when it's really unconditional. // // For example, consider the struct Foo<T: Copy>(*mut T). Using // the original predicates in our impl would cause us to generate // `impl !Send for Foo<T: Copy>`, which makes it appear that Foo // implements Send where T is not copy. // // Instead, we generate `impl !Send for Foo<T>`, which better // expresses the fact that `Foo<T>` never implements `Send`, // regardless of the choice of `T`. let params = (tcx.generics_of(param_env_def_id), ty::GenericPredicates::default()) .clean(self.cx) .params; Generics { params, where_predicates: Vec::new() } } AutoTraitResult::ExplicitImpl => return None, }; Some(Item { source: Span::dummy(), name: None, attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(param_env_def_id.krate), kind: box ImplItem(Impl { unsafety: hir::Unsafety::Normal, generics: new_generics, provided_trait_methods: Default::default(), trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), for_: ty.clean(self.cx), items: Vec::new(), negative_polarity, synthetic: true, blanket_impl: None, }), }) </del> <ins> self.generate_for_trait(ty, trait_def_id, param_env, param_env_def_id, &f, false) </ins> }) <del> .collect() </del> <ins> .collect(); // We are only interested in case the type *doesn't* implement the Sized trait. if !ty.is_sized(self.cx.tcx.at(rustc_span::DUMMY_SP), param_env) { // In case `#![no_core]` is used, `sized_trait` returns nothing. if let Some(item) = self.cx.tcx.lang_items().sized_trait().and_then(|sized_trait_did| { self.generate_for_trait(ty, sized_trait_did, param_env, param_env_def_id, &f, true) }) { auto_traits.push(item); } } auto_traits </ins> } fn get_lifetime(region: Region<'_>, names_map: &FxHashMap<Symbol, Lifetime>) -> Lifetime {


Question:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim

}; use crate::clean; <ins> use crate::clean::inline::build_external_trait; </ins> use crate::clean::{AttributesExt, MAX_DEF_IDX}; use crate::config::{Options as RustdocOptions, RenderOptions}; use crate::config::{OutputFormat, RenderInfo};


Question:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim

module_trait_cache: RefCell::new(FxHashMap::default()), cache: Cache::default(), }; <ins> // Small hack to force the Sized trait to be present. // // Note that in case of `#![no_core]`, the trait is not available. if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() { let mut sized_trait = build_external_trait(&mut ctxt, sized_trait_did); sized_trait.is_auto = true; ctxt.external_traits.borrow_mut().insert(sized_trait_did, sized_trait); } </ins> debug!("crate: {:?}", tcx.hir().krate()); let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));


Question:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim

<ins> #![crate_name = "foo"] // @has foo/struct.Bar.html // @!has - '//h3[@id="impl-Sized"]' pub struct Bar { a: u16, } // @has foo/struct.Foo.html // @!has - '//h3[@id="impl-Sized"]' pub struct Foo<T: ?Sized>(T); // @has foo/struct.Unsized.html // @has - '//h3[@id="impl-Sized"]/code' 'impl !Sized for Unsized' pub struct Unsized { data: [u8], } </ins>


Question:
If you have a function like this: we should report an error. The only thing you could legally do in that case is fail or return a static item, so you miight as well write: This sounds like a good lint warning/error.
My vote is warning rather than error. If you're right that it's always the wrong thing to do, then you shouldn't be able to write non-unsafe code that does this that doesn't error somewhere else. And maybe you want to try doing it just while hacking / experimenting with the language.
Reproduced with This compiles successfully.
Not critical for 0.6; removing milestone
Reproduced with Still compiles successfully.
Nominating for milestone 5, production-ready
just a bug, removing milestone/nomination.
Visiting for triage email 2013-07-22 reproduced with
As of lifetime elision () we now indeed require a bound in that position. Closing.

// except according to those terms. // xfail-test <del> fn foo() -> &'a int { </del> <ins> fn foo<'a>() -> &'a int {  //~ ERROR unconstrained region </ins> return &x; } static x: int = 5;


Question:
I build rustc from source with to get output from to chase down an ICE, and the resulting compiler is about 25 times slower than Nigthly on the same commit. (Servo’s script crate takes ~50 minutes instead of ~2 to trigger the same ICE, .) said on IRC: … which would explain the slowdown, but I didn’t find an issue filed for it, so here it is. This may be a Makefile issue: .
See and . The latter is specifically about optimizations and supposed to be fixed by . Is this still a problem (again) or are you building an older version of the compiler?
Oh you can explain it in different ways, see
should be good enough btw
I’m building 2015-04-25. I believe (which I had found) is not related but kind of is. I can try as suggests, but since lists and not I was lead to believe that enabling optimizations was the default. Is it not? Or is is tied to ? If so, why?
i think this may be "by design", according to discussion on and . Although then again it is not clear that there was consensus on that should imply (though my reading of the comments there that at least some of the participants were in favor of it having that effect). The intention, as I understand it, is that if you do , then you want an "ideal" environment for debugging, which for some people implies "do not let LLVM optimizations get in the way of my debugging experience." The problem with this reasoning is that bootstrapping takes an absurdly long time with . So in practice I do not see how one could realistically actually use without also including to override what it is doing today. (At this point I essentially always call via a driver script that passes explicit switches based on local filesystem context.) Anyway, I would not object if we went back and again decoupled the configure setting from the configure setting. (The argument for why "should" imply , as noted in the relevant , was that 2-3 flags for configure the build is too many, and therefore we wanted to identify two "modes": release mode and developer mode, and then choosing your mode via would yield the "ideal" experience for that mode. This all sounds fine, but I clearly take issue with the claim that is part of anyone's ideal developer mode.)
I can imagine the logic behind this, but in practice this is far from ideal. It’s only one data point, but here is how my thought process and experience went: I hit an ICE and I don’t know the exact cause Asking on IRC, I’m recommended to retry with There is no log output. I assume logging is disabled on my Rust build I decide to try making another build where they’re enabled. I look at . seems relevant, it probably enables logging. I note that is listed as an option, but is not. I assume this means my build will be optimized. This is what I want. The build is taking a while. I know Rust takes a long time to bootstrap and all, but this seems longer than usual. I go do something else. The build ended up taking just over 4 hours. I start building Servo with this new rustc. Cargo somehow decide to rebuild everything, even though I was careful to pick the same Rust commit. This takes another 2 hours, instead of the usual ~8 minutes. Every rebuild of just Servo’s script crate (where the ICE is triggered) now takes over 50 minutes instead of ~2.
Reopening: while documentation helps, I still think we should address the root problem here. See: (And maybe I'll just put up a PR changing the configure script to make it stop doing this.)
I agree with and that in practice you do not want to disable optimizations, and we should not do so without an explicit . This is extra true now that the debuginfo includes inlined functions fairly reliably even in optimized builds (at least on linux): getting a complete backtrace was the only reason I ever resorted to in the past, and it was always painfully slow.
This still seems to be the case, but hasn't been motivation to fix.
This bothers me every time someone accidentally does it, but I didn't even know this issue was open.
I still think we ought to change it. =)
Maybe we can force people to choose between and when is on. That way you can never misunderstand the role of . Like, when we trigger an error: Edit: I forgot we already switched to rustbuild, but you get what I mean
I'm still waiting for someone to come up with an usecase for an unoptimized compiler.
I thought you are the one who may find some clues. Doesn't it help you to decide a tricky behaviour of a compile result is caused by LLVM or rustc? I have no idea.
in theory yes, in practice I've yet to have such a bug (well, I did have one once, actually, but I didn't find it by turning off optimizations); in general an unopt compiler is just too slow to use.
Isn't this fixed by that is, these are all separate options now.
still exists and rustbuild reads .
also, regardless of the existence of , the code for building the bootstrap config from the still ties them together; see here: note in particular that bit about how the is established by the presence of the setting, and then that affects the default value for if it hasn't been explicitly established in the . My proposal is that we stop having the default here (solely for bootstrap builds) be affected by the setting for above it. (And update the docs/messages elsewhere in e.g. accordingly)
Note also that the doc comment for doesn't mention the influence of on its value. It gives this dire warning about having set to false, but the implication of the doc comment is that its always defaulting to :

BOOL_OPTIONS="" VAL_OPTIONS="" <del> opt debug 0 "debug mode" </del> <ins> opt debug 0 "debug mode; disables optimization unless `--enable-optimize` given" </ins> opt valgrind 0 "run tests with valgrind (memcheck by default)" opt helgrind 0 "run tests with helgrind instead of memcheck" opt valgrind-rpass 1 "run rpass-valgrind tests with valgrind"


Question:
I'm not sure if this is an oversight. But the implementation should be trivial. I'll add tests and implement it, if it is fine.
Strings aren't indexable and .len() doesn't count the number of chars. :smile: What comes to mind first is an iterator inspecting the two first chars:
xD I didn't test my code, but you get the gist. I had a impl at first, but then edited it
cc
Triage: this has not been .
PRs welcome!
I can take this. I was also thinking of adding a impl for , but unsure if it would be better to wait for to get closer to stabilization and use that instead of adding another empty enum to std
wait, that wouldn't work bc of lifetime issues regardless, right? :(

<ins> # `char_error_internals` This feature is internal to the Rust compiler and is not intended for general use. ------------------------ </ins>


Question:
I'm not sure if this is an oversight. But the implementation should be trivial. I'll add tests and implement it, if it is fine.
Strings aren't indexable and .len() doesn't count the number of chars. :smile: What comes to mind first is an iterator inspecting the two first chars:
xD I didn't test my code, but you get the gist. I had a impl at first, but then edited it
cc
Triage: this has not been .
PRs welcome!
I can take this. I was also thinking of adding a impl for , but unsure if it would be better to wait for to get closer to stabilization and use that instead of adding another empty enum to std
wait, that wouldn't work bc of lifetime issues regardless, right? :(

use convert::TryFrom; use fmt::{self, Write}; use slice; <del> use str::from_utf8_unchecked_mut; </del> <ins> use str::{from_utf8_unchecked_mut, FromStr}; </ins> use iter::FusedIterator; use mem::transmute;


Question:
I'm not sure if this is an oversight. But the implementation should be trivial. I'll add tests and implement it, if it is fine.
Strings aren't indexable and .len() doesn't count the number of chars. :smile: What comes to mind first is an iterator inspecting the two first chars:
xD I didn't test my code, but you get the gist. I had a impl at first, but then edited it
cc
Triage: this has not been .
PRs welcome!
I can take this. I was also thinking of adding a impl for , but unsure if it would be better to wait for to get closer to stabilization and use that instead of adding another empty enum to std
wait, that wouldn't work bc of lifetime issues regardless, right? :(

} } <ins> /// An error which can be returned when parsing a char. #[stable(feature = "char_from_str", since = "1.19.0")] #[derive(Clone, Debug)] pub struct ParseCharError { kind: CharErrorKind, } impl ParseCharError { #[unstable(feature = "char_error_internals", reason = "this method should not be available publicly", issue = "0")] #[doc(hidden)] pub fn __description(&self) -> &str { match self.kind { CharErrorKind::EmptyString => { "cannot parse char from empty string" }, CharErrorKind::TooManyChars => "too many characters in string" } } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum CharErrorKind { EmptyString, TooManyChars, } #[stable(feature = "char_from_str", since = "1.19.0")] impl fmt::Display for ParseCharError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.__description().fmt(f) } } #[stable(feature = "char_from_str", since = "1.19.0")] impl FromStr for char { type Err = ParseCharError; #[inline] fn from_str(s: &str) -> Result<Self, Self::Err> { let mut chars = s.chars(); match (chars.next(), chars.next()) { (None, _) => { Err(ParseCharError { kind: CharErrorKind::EmptyString }) }, (Some(c), None) => Ok(c), _ => { Err(ParseCharError { kind: CharErrorKind::TooManyChars }) } } } } </ins> #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<u32> for char { type Error = CharTryFromError;


Question:
I'm not sure if this is an oversight. But the implementation should be trivial. I'll add tests and implement it, if it is fine.
Strings aren't indexable and .len() doesn't count the number of chars. :smile: What comes to mind first is an iterator inspecting the two first chars:
xD I didn't test my code, but you get the gist. I had a impl at first, but then edited it
cc
Triage: this has not been .
PRs welcome!
I can take this. I was also thinking of adding a impl for , but unsure if it would be better to wait for to get closer to stabilization and use that instead of adding another empty enum to std
wait, that wouldn't work bc of lifetime issues regardless, right? :(

use std::{char,str}; use std::convert::TryFrom; <ins> use std::str::FromStr; </ins> #[test] fn test_convert() {


Question:
I'm not sure if this is an oversight. But the implementation should be trivial. I'll add tests and implement it, if it is fine.
Strings aren't indexable and .len() doesn't count the number of chars. :smile: What comes to mind first is an iterator inspecting the two first chars:
xD I didn't test my code, but you get the gist. I had a impl at first, but then edited it
cc
Triage: this has not been .
PRs welcome!
I can take this. I was also thinking of adding a impl for , but unsure if it would be better to wait for to get closer to stabilization and use that instead of adding another empty enum to std
wait, that wouldn't work bc of lifetime issues regardless, right? :(

} #[test] <ins> fn test_from_str() { assert_eq!(char::from_str("a").unwrap(), 'a'); assert_eq!(char::try_from("a").unwrap(), 'a'); assert_eq!(char::from_str("0").unwrap(), '0'); assert_eq!(char::from_str("u{D7FF}").unwrap(), 'u{d7FF}'); assert!(char::from_str("").is_err()); assert!(char::from_str("abc").is_err()); } #[test] </ins> fn test_is_lowercase() { assert!('a'.is_lowercase()); assert!('ö'.is_lowercase());


Question:
I'm not sure if this is an oversight. But the implementation should be trivial. I'll add tests and implement it, if it is fine.
Strings aren't indexable and .len() doesn't count the number of chars. :smile: What comes to mind first is an iterator inspecting the two first chars:
xD I didn't test my code, but you get the gist. I had a impl at first, but then edited it
cc
Triage: this has not been .
PRs welcome!
I can take this. I was also thinking of adding a impl for , but unsure if it would be better to wait for to get closer to stabilization and use that instead of adding another empty enum to std
wait, that wouldn't work bc of lifetime issues regardless, right? :(

} } <ins> #[stable(feature = "char_from_str", since = "1.19.0")] impl Error for char::ParseCharError { fn description(&self) -> &str { self.__description() } } </ins> // copied from any.rs impl Error + 'static { /// Returns true if the boxed type is the same as `T`


Question:
I'm not sure if this is an oversight. But the implementation should be trivial. I'll add tests and implement it, if it is fine.
Strings aren't indexable and .len() doesn't count the number of chars. :smile: What comes to mind first is an iterator inspecting the two first chars:
xD I didn't test my code, but you get the gist. I had a impl at first, but then edited it
cc
Triage: this has not been .
PRs welcome!
I can take this. I was also thinking of adding a impl for , but unsure if it would be better to wait for to get closer to stabilization and use that instead of adding another empty enum to std
wait, that wouldn't work bc of lifetime issues regardless, right? :(

#![feature(cfg_target_thread_local)] #![feature(cfg_target_vendor)] #![feature(char_escape_debug)] <ins> #![feature(char_error_internals)] </ins> #![feature(char_internals)] #![feature(collections)] #![feature(collections_range)]


Question:
I'm not sure if this is an oversight. But the implementation should be trivial. I'll add tests and implement it, if it is fine.
Strings aren't indexable and .len() doesn't count the number of chars. :smile: What comes to mind first is an iterator inspecting the two first chars:
xD I didn't test my code, but you get the gist. I had a impl at first, but then edited it
cc
Triage: this has not been .
PRs welcome!
I can take this. I was also thinking of adding a impl for , but unsure if it would be better to wait for to get closer to stabilization and use that instead of adding another empty enum to std
wait, that wouldn't work bc of lifetime issues regardless, right? :(

pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::char::{EscapeDebug, EscapeDefault, EscapeUnicode}; <ins> #[stable(feature = "char_from_str", since = "1.19.0")] pub use core::char::ParseCharError; </ins> // unstable reexports #[unstable(feature = "try_from", issue = "33417")]


Question:
blksizet on 64-bit FreeBSD is 32 bits, not 64. on FreeBSD x8664 yields: yields: I tracked this down to the type definition, which is unconditionally 32-bit on FreeBSD (see , noting this line: this is unconditionally the definition of on FreeBSD - whether on 32-bit or 64-bit platform.)
Also, is a no-op (two fields of size 0) on 64-bit FreeBSD, the field can be deleted from the structure.

use types::os::arch::posix88::{uid_t}; pub type nlink_t = u16; <del> pub type blksize_t = i32; </del> <ins> pub type blksize_t = u32; </ins> pub type blkcnt_t = i64; pub type fflags_t = u32; #[repr(C)]


Question:
blksizet on 64-bit FreeBSD is 32 bits, not 64. on FreeBSD x8664 yields: yields: I tracked this down to the type definition, which is unconditionally 32-bit on FreeBSD (see , noting this line: this is unconditionally the definition of on FreeBSD - whether on 32-bit or 64-bit platform.)
Also, is a no-op (two fields of size 0) on 64-bit FreeBSD, the field can be deleted from the structure.

pub st_lspare: int32_t, pub st_birthtime: time_t, pub st_birthtime_nsec: c_long, <del> pub __unused: [uint8_t; 2], </del> <ins> pub __unused: [u8; 8], </ins> } #[repr(C)]


Question:
blksizet on 64-bit FreeBSD is 32 bits, not 64. on FreeBSD x8664 yields: yields: I tracked this down to the type definition, which is unconditionally 32-bit on FreeBSD (see , noting this line: this is unconditionally the definition of on FreeBSD - whether on 32-bit or 64-bit platform.)
Also, is a no-op (two fields of size 0) on 64-bit FreeBSD, the field can be deleted from the structure.

use types::os::arch::posix88::{uid_t}; pub type nlink_t = u16; <del> pub type blksize_t = i64; </del> <ins> pub type blksize_t = u32; </ins> pub type blkcnt_t = i64; pub type fflags_t = u32; #[repr(C)]


Question:
blksizet on 64-bit FreeBSD is 32 bits, not 64. on FreeBSD x8664 yields: yields: I tracked this down to the type definition, which is unconditionally 32-bit on FreeBSD (see , noting this line: this is unconditionally the definition of on FreeBSD - whether on 32-bit or 64-bit platform.)
Also, is a no-op (two fields of size 0) on 64-bit FreeBSD, the field can be deleted from the structure.

pub st_lspare: int32_t, pub st_birthtime: time_t, pub st_birthtime_nsec: c_long, <del> pub __unused: [uint8_t; 2], </del> } #[repr(C)]


Question:
blksizet on 64-bit FreeBSD is 32 bits, not 64. on FreeBSD x8664 yields: yields: I tracked this down to the type definition, which is unconditionally 32-bit on FreeBSD (see , noting this line: this is unconditionally the definition of on FreeBSD - whether on 32-bit or 64-bit platform.)
Also, is a no-op (two fields of size 0) on 64-bit FreeBSD, the field can be deleted from the structure.

#![stable(feature = "raw_ext", since = "1.1.0")] <del> use os::raw::c_long; use os::unix::raw::{uid_t, gid_t}; </del> <ins> #[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = i64; #[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u16; #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u16; #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64; #[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32; </ins> <del> #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64; #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = i64; #[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u16; #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u16; #[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = i64; #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64; </del> <ins> #[doc(inline)] pub use self::arch::{stat, time_t}; </ins> <del> #[repr(C)] #[stable(feature = "raw_ext", since = "1.1.0")] pub struct stat { #[stable(feature = "raw_ext", since = "1.1.0")] pub st_dev: dev_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ino: ino_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mode: mode_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_nlink: nlink_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_uid: uid_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_gid: gid_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_rdev: dev_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_atime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_atime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mtime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mtime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ctime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ctime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_size: off_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blocks: blkcnt_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blksize: blksize_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_flags: fflags_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_gen: u32, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_lspare: i32, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_birthtime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_birthtime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub __unused: [u8; 2], </del> <ins> #[cfg(target_arch = "x86")] mod arch { use super::{off_t, dev_t, ino_t, mode_t, nlink_t, blksize_t, blkcnt_t, fflags_t}; use os::raw::c_long; use os::unix::raw::{uid_t, gid_t}; #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i32; #[repr(C)] #[stable(feature = "raw_ext", since = "1.1.0")] pub struct stat { #[stable(feature = "raw_ext", since = "1.1.0")] pub st_dev: dev_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ino: ino_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mode: mode_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_nlink: nlink_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_uid: uid_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_gid: gid_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_rdev: dev_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_atime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_atime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mtime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mtime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ctime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ctime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_size: off_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blocks: blkcnt_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blksize: blksize_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_flags: fflags_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_gen: u32, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_lspare: i32, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_birthtime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_birthtime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub __unused: [u8; 8], } </ins> } <ins> #[cfg(target_arch = "x86_64")] mod arch { use super::{off_t, dev_t, ino_t, mode_t, nlink_t, blksize_t, blkcnt_t, fflags_t}; use os::raw::c_long; use os::unix::raw::{uid_t, gid_t}; #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64; #[repr(C)] #[stable(feature = "raw_ext", since = "1.1.0")] pub struct stat { #[stable(feature = "raw_ext", since = "1.1.0")] pub st_dev: dev_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ino: ino_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mode: mode_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_nlink: nlink_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_uid: uid_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_gid: gid_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_rdev: dev_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_atime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_atime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mtime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mtime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ctime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ctime_nsec: c_long, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_size: off_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blocks: blkcnt_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blksize: blksize_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_flags: fflags_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_gen: u32, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_lspare: i32, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_birthtime: time_t, #[stable(feature = "raw_ext", since = "1.1.0")] pub st_birthtime_nsec: c_long, } } </ins>


Question:
The following function can drop any object arbitrary number of times, using only safe code: Probably bad :) Found while researching
Nominating for P-high
cc
Too bad this doesn't just cancel out the Leakocalypse :stuckouttongue:
(well, any object that implements . But yes, I see the point being made here.)
look, no required. I guess it doesn't work for types that are already unsized.
to be clear, I am looking at this now as well. :)
I guess is related.
I hope it is unrelated. In particular I wrote this on that ticket:
Yeah, it's unrelated. The call happens for , which does need drop.

let info = Load(bcx, get_len(bcx, base_datum.val)); Store(bcx, info, get_len(bcx, scratch.val)); <del> DatumBlock::new(bcx, scratch.to_expr_datum()) </del> <ins> // Always generate an lvalue datum, because this pointer doesn't own // the data and cleanup is scheduled elsewhere. DatumBlock::new(bcx, Datum::new(scratch.val, scratch.ty, LvalueExpr)) </ins> } })


Question:
The following function can drop any object arbitrary number of times, using only safe code: Probably bad :) Found while researching
Nominating for P-high
cc
Too bad this doesn't just cancel out the Leakocalypse :stuckouttongue:
(well, any object that implements . But yes, I see the point being made here.)
look, no required. I guess it doesn't work for types that are already unsized.
to be clear, I am looking at this now as well. :)
I guess is related.
I hope it is unrelated. In particular I wrote this on that ticket:
Yeah, it's unrelated. The call happens for , which does need drop.

<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::rc::Rc; struct Foo<'r>(&'r mut i32); impl<'r> Drop for Foo<'r> { fn drop(&mut self) { *self.0 += 1; } } fn main() { let mut drops = 0; { let _: Rc<Send> = Rc::new(Foo(&mut drops)); } assert_eq!(1, drops); } </ins>


Question:
The following function can drop any object arbitrary number of times, using only safe code: Probably bad :) Found while researching
Nominating for P-high
cc
Too bad this doesn't just cancel out the Leakocalypse :stuckouttongue:
(well, any object that implements . But yes, I see the point being made here.)
look, no required. I guess it doesn't work for types that are already unsized.
to be clear, I am looking at this now as well. :)
I guess is related.
I hope it is unrelated. In particular I wrote this on that ticket:
Yeah, it's unrelated. The call happens for , which does need drop.

<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. struct Foo<'r>(&'r mut i32); impl<'r> Drop for Foo<'r> { fn drop(&mut self) { *self.0 += 1; } } trait Trait {} impl<'r> Trait for Foo<'r> {} struct Holder<T: ?Sized>(T); fn main() { let mut drops = 0; { let y = &Holder([Foo(&mut drops)]) as &Holder<[Foo]>; // this used to cause an extra drop of the Foo instance let x = &y.0; } assert_eq!(1, drops); drops = 0; { let y = &Holder(Foo(&mut drops)) as &Holder<Trait>; // this used to cause an extra drop of the Foo instance let x = &y.0; } assert_eq!(1, drops); } </ins>


Question: The grammar of given in the is outdated: the mandatory semicolon at the end of the first rule is missing, and an alternative notation using the curly brackets is missing as well. Regards, Ivan

## Macros ```antlr <del> expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ; </del> <ins> expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ';' | "macro_rules" '!' ident '{' macro_rule * '}' ; </ins> macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';' ; matcher : '(' matcher * ')' | '[' matcher * ']' | '{' matcher * '}' | '$' ident ':' ident


Question:
This takes ~2 seconds to type check (according to ): Doubling (respectively, halving) the number of invocations multiplies (resp. divides) the time by 4. It applies to arithmetic in s/s too which is, I imagine, where this will occur most often in practice (it's how I found it). Observations: for , , and , annotating either side (e.g. ) or both sides makes it take only 0.03s and behave linearly (AFAICT) for and : annotating the LHS () reduces the time to ~1.5s, annotating the RHS () reduces it to ~1.1s but both are still quadratic, annotating both takes it to 0.04s and linear it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s. there's no significant difference between using the macro or writing the operations inline (I only use to allow easier experimentation) cc
This must be what's making my old macro-abusing inflate implementation take almost 300 seconds in typeck. It almost sounds like type-checking a function is quadratic over the number of inference variables. Having ran callgrind on the sample and also half of it, I'm seeing the following trace: An unrefined conclusion is that either shouldn't call or should be constant-time.
Is this the same issue as ?
I'm not too familiar with fulfill and infer, but couldn't track the latest snapshot it processed and look at the new information there?
We have exactly for this reason. It doesn't work for some reason tho.
This is the same issue as This is a different issue from (I think I will fix that one separately).

use dep_graph::DepGraph; use middle::infer::InferCtxt; <del> use middle::ty::{self, Ty, TypeFoldable}; </del> <ins> use middle::ty::{self, Ty, TypeFoldable, ToPolyTraitRef}; </ins> use rustc_data_structures::obligation_forest::{Backtrace, ObligationForest, Error}; use std::iter; use syntax::ast;


Question:
This takes ~2 seconds to type check (according to ): Doubling (respectively, halving) the number of invocations multiplies (resp. divides) the time by 4. It applies to arithmetic in s/s too which is, I imagine, where this will occur most often in practice (it's how I found it). Observations: for , , and , annotating either side (e.g. ) or both sides makes it take only 0.03s and behave linearly (AFAICT) for and : annotating the LHS () reduces the time to ~1.5s, annotating the RHS () reduces it to ~1.1s but both are still quadratic, annotating both takes it to 0.04s and linear it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s. there's no significant difference between using the macro or writing the operations inline (I only use to allow easier experimentation) cc
This must be what's making my old macro-abusing inflate implementation take almost 300 seconds in typeck. It almost sounds like type-checking a function is quadratic over the number of inference variables. Having ran callgrind on the sample and also half of it, I'm seeing the following trace: An unrefined conclusion is that either shouldn't call or should be constant-time.
Is this the same issue as ?
I'm not too familiar with fulfill and infer, but couldn't track the latest snapshot it processed and look at the new information there?
We have exactly for this reason. It doesn't work for some reason tho.
This is the same issue as This is a different issue from (I think I will fix that one separately).

} } <ins> /// Return the set of type variables contained in a trait ref fn trait_ref_type_vars<'a, 'tcx>(selcx: &mut SelectionContext<'a, 'tcx>, t: ty::PolyTraitRef<'tcx>) -> Vec<Ty<'tcx>> { t.skip_binder() // ok b/c this check doesn't care about regions .input_types() .iter() .map(|t| selcx.infcx().resolve_type_vars_if_possible(t)) .filter(|t| t.has_infer_types()) .flat_map(|t| t.walk()) .filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false }) .collect() } </ins> /// Processes a predicate obligation and returns either: /// - `Ok(Some(v))` if the predicate is true, presuming that `v` are also true /// - `Ok(None)` if we don't have enough info to be sure


Question:
This takes ~2 seconds to type check (according to ): Doubling (respectively, halving) the number of invocations multiplies (resp. divides) the time by 4. It applies to arithmetic in s/s too which is, I imagine, where this will occur most often in practice (it's how I found it). Observations: for , , and , annotating either side (e.g. ) or both sides makes it take only 0.03s and behave linearly (AFAICT) for and : annotating the LHS () reduces the time to ~1.5s, annotating the RHS () reduces it to ~1.1s but both are still quadratic, annotating both takes it to 0.04s and linear it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s. there's no significant difference between using the macro or writing the operations inline (I only use to allow easier experimentation) cc
This must be what's making my old macro-abusing inflate implementation take almost 300 seconds in typeck. It almost sounds like type-checking a function is quadratic over the number of inference variables. Having ran callgrind on the sample and also half of it, I'm seeing the following trace: An unrefined conclusion is that either shouldn't call or should be constant-time.
Is this the same issue as ?
I'm not too familiar with fulfill and infer, but couldn't track the latest snapshot it processed and look at the new information there?
We have exactly for this reason. It doesn't work for some reason tho.
This is the same issue as This is a different issue from (I think I will fix that one separately).

// doing more work yet if !pending_obligation.stalled_on.is_empty() { if pending_obligation.stalled_on.iter().all(|&ty| { <del> let resolved_ty = selcx.infcx().resolve_type_vars_if_possible(&ty); </del> <ins> let resolved_ty = selcx.infcx().shallow_resolve(&ty); </ins> resolved_ty == ty // nothing changed here }) { debug!("process_predicate: pending obligation {:?} still stalled on {:?}",


Question:
This takes ~2 seconds to type check (according to ): Doubling (respectively, halving) the number of invocations multiplies (resp. divides) the time by 4. It applies to arithmetic in s/s too which is, I imagine, where this will occur most often in practice (it's how I found it). Observations: for , , and , annotating either side (e.g. ) or both sides makes it take only 0.03s and behave linearly (AFAICT) for and : annotating the LHS () reduces the time to ~1.5s, annotating the RHS () reduces it to ~1.1s but both are still quadratic, annotating both takes it to 0.04s and linear it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s. there's no significant difference between using the macro or writing the operations inline (I only use to allow easier experimentation) cc
This must be what's making my old macro-abusing inflate implementation take almost 300 seconds in typeck. It almost sounds like type-checking a function is quadratic over the number of inference variables. Having ran callgrind on the sample and also half of it, I'm seeing the following trace: An unrefined conclusion is that either shouldn't call or should be constant-time.
Is this the same issue as ?
I'm not too familiar with fulfill and infer, but couldn't track the latest snapshot it processed and look at the new information there?
We have exactly for this reason. It doesn't work for some reason tho.
This is the same issue as This is a different issue from (I think I will fix that one separately).

// of its type, and those types are resolved at // the same time. pending_obligation.stalled_on = <del> data.skip_binder() // ok b/c this check doesn't care about regions .input_types() .iter() .map(|t| selcx.infcx().resolve_type_vars_if_possible(t)) .filter(|t| t.has_infer_types()) .flat_map(|t| t.walk()) .filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false }) .collect(); </del> <ins> trait_ref_type_vars(selcx, data.to_poly_trait_ref()); </ins> debug!("process_predicate: pending obligation {:?} now stalled on {:?}", selcx.infcx().resolve_type_vars_if_possible(obligation),


Question:
This takes ~2 seconds to type check (according to ): Doubling (respectively, halving) the number of invocations multiplies (resp. divides) the time by 4. It applies to arithmetic in s/s too which is, I imagine, where this will occur most often in practice (it's how I found it). Observations: for , , and , annotating either side (e.g. ) or both sides makes it take only 0.03s and behave linearly (AFAICT) for and : annotating the LHS () reduces the time to ~1.5s, annotating the RHS () reduces it to ~1.1s but both are still quadratic, annotating both takes it to 0.04s and linear it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s. there's no significant difference between using the macro or writing the operations inline (I only use to allow easier experimentation) cc
This must be what's making my old macro-abusing inflate implementation take almost 300 seconds in typeck. It almost sounds like type-checking a function is quadratic over the number of inference variables. Having ran callgrind on the sample and also half of it, I'm seeing the following trace: An unrefined conclusion is that either shouldn't call or should be constant-time.
Is this the same issue as ?
I'm not too familiar with fulfill and infer, but couldn't track the latest snapshot it processed and look at the new information there?
We have exactly for this reason. It doesn't work for some reason tho.
This is the same issue as This is a different issue from (I think I will fix that one separately).

ty::Predicate::Projection(ref data) => { let project_obligation = obligation.with(data.clone()); match project::poly_project_and_unify_type(selcx, &project_obligation) { <ins> Ok(None) => { pending_obligation.stalled_on = trait_ref_type_vars(selcx, data.to_poly_trait_ref()); Ok(None) } </ins> Ok(v) => Ok(v), Err(e) => Err(CodeProjectionError(e)) }


Question:
This takes ~2 seconds to type check (according to ): Doubling (respectively, halving) the number of invocations multiplies (resp. divides) the time by 4. It applies to arithmetic in s/s too which is, I imagine, where this will occur most often in practice (it's how I found it). Observations: for , , and , annotating either side (e.g. ) or both sides makes it take only 0.03s and behave linearly (AFAICT) for and : annotating the LHS () reduces the time to ~1.5s, annotating the RHS () reduces it to ~1.1s but both are still quadratic, annotating both takes it to 0.04s and linear it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s. there's no significant difference between using the macro or writing the operations inline (I only use to allow easier experimentation) cc
This must be what's making my old macro-abusing inflate implementation take almost 300 seconds in typeck. It almost sounds like type-checking a function is quadratic over the number of inference variables. Having ran callgrind on the sample and also half of it, I'm seeing the following trace: An unrefined conclusion is that either shouldn't call or should be constant-time.
Is this the same issue as ?
I'm not too familiar with fulfill and infer, but couldn't track the latest snapshot it processed and look at the new information there?
We have exactly for this reason. It doesn't work for some reason tho.
This is the same issue as This is a different issue from (I think I will fix that one separately).

} ty::Predicate::WellFormed(ty) => { <del> Ok(ty::wf::obligations(selcx.infcx(), obligation.cause.body_id, ty, obligation.cause.span)) </del> <ins> match ty::wf::obligations(selcx.infcx(), obligation.cause.body_id, ty, obligation.cause.span) { None => { pending_obligation.stalled_on = vec![ty]; Ok(None) } s => Ok(s) } </ins> } } }


Question:
This takes ~2 seconds to type check (according to ): Doubling (respectively, halving) the number of invocations multiplies (resp. divides) the time by 4. It applies to arithmetic in s/s too which is, I imagine, where this will occur most often in practice (it's how I found it). Observations: for , , and , annotating either side (e.g. ) or both sides makes it take only 0.03s and behave linearly (AFAICT) for and : annotating the LHS () reduces the time to ~1.5s, annotating the RHS () reduces it to ~1.1s but both are still quadratic, annotating both takes it to 0.04s and linear it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s. there's no significant difference between using the macro or writing the operations inline (I only use to allow easier experimentation) cc
This must be what's making my old macro-abusing inflate implementation take almost 300 seconds in typeck. It almost sounds like type-checking a function is quadratic over the number of inference variables. Having ran callgrind on the sample and also half of it, I'm seeing the following trace: An unrefined conclusion is that either shouldn't call or should be constant-time.
Is this the same issue as ?
I'm not too familiar with fulfill and infer, but couldn't track the latest snapshot it processed and look at the new information there?
We have exactly for this reason. It doesn't work for some reason tho.
This is the same issue as This is a different issue from (I think I will fix that one separately).

impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { <del> self.map_bound_ref(|trait_pred| trait_pred.trait_ref.clone()) </del> <ins> self.map_bound_ref(|trait_pred| trait_pred.trait_ref) </ins> } }


Question:
This takes ~2 seconds to type check (according to ): Doubling (respectively, halving) the number of invocations multiplies (resp. divides) the time by 4. It applies to arithmetic in s/s too which is, I imagine, where this will occur most often in practice (it's how I found it). Observations: for , , and , annotating either side (e.g. ) or both sides makes it take only 0.03s and behave linearly (AFAICT) for and : annotating the LHS () reduces the time to ~1.5s, annotating the RHS () reduces it to ~1.1s but both are still quadratic, annotating both takes it to 0.04s and linear it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s. there's no significant difference between using the macro or writing the operations inline (I only use to allow easier experimentation) cc
This must be what's making my old macro-abusing inflate implementation take almost 300 seconds in typeck. It almost sounds like type-checking a function is quadratic over the number of inference variables. Having ran callgrind on the sample and also half of it, I'm seeing the following trace: An unrefined conclusion is that either shouldn't call or should be constant-time.
Is this the same issue as ?
I'm not too familiar with fulfill and infer, but couldn't track the latest snapshot it processed and look at the new information there?
We have exactly for this reason. It doesn't work for some reason tho.
This is the same issue as This is a different issue from (I think I will fix that one separately).

// This is because here `self` has a `Binder` and so does our // return value, so we are preserving the number of binding // levels. <del> ty::Binder(self.0.projection_ty.trait_ref.clone()) </del> <ins> ty::Binder(self.0.projection_ty.trait_ref) </ins> } }


Question:
This takes ~2 seconds to type check (according to ): Doubling (respectively, halving) the number of invocations multiplies (resp. divides) the time by 4. It applies to arithmetic in s/s too which is, I imagine, where this will occur most often in practice (it's how I found it). Observations: for , , and , annotating either side (e.g. ) or both sides makes it take only 0.03s and behave linearly (AFAICT) for and : annotating the LHS () reduces the time to ~1.5s, annotating the RHS () reduces it to ~1.1s but both are still quadratic, annotating both takes it to 0.04s and linear it seems to only be dependent on the number of operations in a single function/item, separating the 4 big chunks above across 4 functions reduces the time to ~0.5s. there's no significant difference between using the macro or writing the operations inline (I only use to allow easier experimentation) cc
This must be what's making my old macro-abusing inflate implementation take almost 300 seconds in typeck. It almost sounds like type-checking a function is quadratic over the number of inference variables. Having ran callgrind on the sample and also half of it, I'm seeing the following trace: An unrefined conclusion is that either shouldn't call or should be constant-time.
Is this the same issue as ?
I'm not too familiar with fulfill and infer, but couldn't track the latest snapshot it processed and look at the new information there?
We have exactly for this reason. It doesn't work for some reason tho.
This is the same issue as This is a different issue from (I think I will fix that one separately).

<ins> // Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. fn main() { macro_rules! f { () => { 0 + 0 } } // 16 per line f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); } </ins>


Question: All of the following I'm going to describe happens only when expanding doc comments in a macro, using meta fragments, in other contexts it works fine, so it indeed is a thing! A sample of doc comments expansion in a macro can be found at so I'll skip samples and go direct to the point. If I use a escape sequence of usual strings it seems to expand it right there on rustdoc. I have found the issue by trying to do something like the following: When I run I get this panic: When using the outside a code block it does not happen, but if I try a hexadecimal literal outside the code block instead it still panics. I get Interesting but let's try something that is not a null character to see what happens: Ha! I get a in my html output!

tts: vec![TtToken(sp, token::Ident(token::str_to_ident("doc"), token::Plain)), TtToken(sp, token::Eq), <del> TtToken(sp, token::Literal(token::Str_(name), None))], </del> <ins> TtToken(sp, token::Literal(token::StrRaw(name, 0), None))], </ins> close_span: sp, })) }


Question: All of the following I'm going to describe happens only when expanding doc comments in a macro, using meta fragments, in other contexts it works fine, so it indeed is a thing! A sample of doc comments expansion in a macro can be found at so I'll skip samples and go direct to the point. If I use a escape sequence of usual strings it seems to expand it right there on rustdoc. I have found the issue by trying to do something like the following: When I run I get this panic: When using the outside a code block it does not happen, but if I try a hexadecimal literal outside the code block instead it still panics. I get Interesting but let's try something that is not a null character to see what happens: Ha! I get a in my html output!

<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // When expanding a macro, documentation attributes (including documentation comments) must be // passed "as is" without being parsed. Otherwise, some text will be incorrectly interpreted as // escape sequences, leading to an ICE. // // Related issues: #25929, #25943 macro_rules! homura { (#[$x:meta]) => () } homura! { /// madoka x41 } fn main() { } </ins>


Question:
This does generate code that calls in the vtable, but is not particularly useful. cc
Still a problem?
It's still true, but I'm not especially worried about it.
Isn't it a bug that you can declare such a trait at all? There's no way to implement it, right?
This code is now rejected with:

<ins> // ignore-tidy-linelength // regression test for #26376 trait Foo { fn foo(&self) -> [u8]; } fn foo(f: Option<&dyn Foo>) { if let Some(f) = f { let _ = f.foo(); //~^ ERROR cannot move a value of type [u8]: the size of [u8] cannot be statically determined } } fn main() { foo(None) } </ins>


Question:
This does generate code that calls in the vtable, but is not particularly useful. cc
Still a problem?
It's still true, but I'm not especially worried about it.
Isn't it a bug that you can declare such a trait at all? There's no way to implement it, right?
This code is now rejected with:

<ins> error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined --> $DIR/return-unsized-from-trait-method.rs:11:17 | LL |         let _ = f.foo(); |                 ^^^^^^^ error: aborting due to previous error For more information about this error, try `rustc --explain E0161`. </ins>


Question:
Much of the implementation work for rust-lang/rfcs has been done, but there remain some corner cases to fix: [ ] Casts between raw pointers to different traits are accepted but should not be (e.g. ) [ ] Double-check other cases, ensure adequate tests exist
triage: P-high -- I'm giving this high priority since accepting casts that we ought not to is a backwards compatibility risk, though it is mitigated by the fact that afaik the illegal casts yield an ICE (but I haven't done exhaustive testing)
The newly-illegal casts shouldn't be ICE-s (I mean, on nightly). Casts on stable are just randomly ICE-ey.

//! //! where `&.T` and `*T` are references of either mutability, //! and where unsize_kind(`T`) is the kind of the unsize info <del> //! in `T` - a vtable or a length (or `()` if `T: Sized`). </del> <ins> //! in `T` - the vtable for a trait definition (e.g. `fmt::Display` or //! `Iterator`, not `Iterator<Item=u8>`) or a length (or `()` if `T: Sized`). //! //! Note that lengths are not adjusted when casting raw slices - //! `T: *const [u16] as *const [u8]` creates a slice that only includes //! half of the original memory. </ins> //! //! Casting is not transitive, that is, even if `e as U1 as U2` is a valid //! expression, `e as U2` is not necessarily so (in fact it will only be valid if


Question:
Much of the implementation work for rust-lang/rfcs has been done, but there remain some corner cases to fix: [ ] Casts between raw pointers to different traits are accepted but should not be (e.g. ) [ ] Double-check other cases, ensure adequate tests exist
triage: P-high -- I'm giving this high priority since accepting casts that we ought not to is a backwards compatibility risk, though it is mitigated by the fact that afaik the illegal casts yield an ICE (but I haven't done exhaustive testing)
The newly-illegal casts shouldn't be ICE-s (I mean, on nightly). Casts on stable are just randomly ICE-ey.

/// fat pointers if their unsize-infos have the same kind. #[derive(Copy, Clone, PartialEq, Eq)] enum UnsizeKind<'tcx> { <del> Vtable, </del> <ins> Vtable(ast::DefId), </ins> Length, /// The unsize info of this projection OfProjection(&'tcx ty::ProjectionTy<'tcx>),


Question:
Much of the implementation work for rust-lang/rfcs has been done, but there remain some corner cases to fix: [ ] Casts between raw pointers to different traits are accepted but should not be (e.g. ) [ ] Double-check other cases, ensure adequate tests exist
triage: P-high -- I'm giving this high priority since accepting casts that we ought not to is a backwards compatibility risk, though it is mitigated by the fact that afaik the illegal casts yield an ICE (but I haven't done exhaustive testing)
The newly-illegal casts shouldn't be ICE-s (I mean, on nightly). Casts on stable are just randomly ICE-ey.

-> Option<UnsizeKind<'tcx>> { match t.sty { ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length), <del> ty::TyTrait(_) => Some(UnsizeKind::Vtable), </del> <ins> ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())), </ins> ty::TyStruct(did, substs) => { match ty::struct_fields(fcx.tcx(), did, substs).pop() { None => None,


Question:
Much of the implementation work for rust-lang/rfcs has been done, but there remain some corner cases to fix: [ ] Casts between raw pointers to different traits are accepted but should not be (e.g. ) [ ] Double-check other cases, ensure adequate tests exist
triage: P-high -- I'm giving this high priority since accepting casts that we ought not to is a backwards compatibility risk, though it is mitigated by the fact that afaik the illegal casts yield an ICE (but I haven't done exhaustive testing)
The newly-illegal casts shouldn't be ICE-s (I mean, on nightly). Casts on stable are just randomly ICE-ey.

trait Foo { fn foo(&self) {} } impl<T> Foo for T {} <ins> trait Bar { fn foo(&self) {} } impl<T> Bar for T {} </ins> enum E { A, B }


Question:
Much of the implementation work for rust-lang/rfcs has been done, but there remain some corner cases to fix: [ ] Casts between raw pointers to different traits are accepted but should not be (e.g. ) [ ] Double-check other cases, ensure adequate tests exist
triage: P-high -- I'm giving this high priority since accepting casts that we ought not to is a backwards compatibility risk, though it is mitigated by the fact that afaik the illegal casts yield an ICE (but I haven't done exhaustive testing)
The newly-illegal casts shouldn't be ICE-s (I mean, on nightly). Casts on stable are just randomly ICE-ey.

// check no error cascade let _ = main.f as *const u32; //~ ERROR attempted access of field <ins> let cf: *const Foo = &0; let _ = cf as *const [u8]; //~ ERROR vtable kinds let _ = cf as *const Bar; //~ ERROR vtable kinds </ins> }


Question:
Much of the implementation work for rust-lang/rfcs has been done, but there remain some corner cases to fix: [ ] Casts between raw pointers to different traits are accepted but should not be (e.g. ) [ ] Double-check other cases, ensure adequate tests exist
triage: P-high -- I'm giving this high priority since accepting casts that we ought not to is a backwards compatibility risk, though it is mitigated by the fact that afaik the illegal casts yield an ICE (but I haven't done exhaustive testing)
The newly-illegal casts shouldn't be ICE-s (I mean, on nightly). Casts on stable are just randomly ICE-ey.

impl Foo<u32> for u32 { fn foo(&self, _: u32) -> u32 { self+43 } } impl Bar for () {} <del> unsafe fn fool<'a>(t: *const (Foo<u32>+'a)) -> u32 { let bar : *const Bar = t as *const Bar; </del> <ins> unsafe fn round_trip_and_call<'a>(t: *const (Foo<u32>+'a)) -> u32 { </ins> let foo_e : *const Foo<u16> = t as *const _; let r_1 = foo_e as *mut Foo<u32>; <del> (&*r_1).foo(0)*(&*(bar as *const Foo<u32>)).foo(0) </del> <ins> (&*r_1).foo(0) </ins> } #[repr(C)]


Question:
Much of the implementation work for rust-lang/rfcs has been done, but there remain some corner cases to fix: [ ] Casts between raw pointers to different traits are accepted but should not be (e.g. ) [ ] Double-check other cases, ensure adequate tests exist
triage: P-high -- I'm giving this high priority since accepting casts that we ought not to is a backwards compatibility risk, though it is mitigated by the fact that afaik the illegal casts yield an ICE (but I haven't done exhaustive testing)
The newly-illegal casts shouldn't be ICE-s (I mean, on nightly). Casts on stable are just randomly ICE-ey.

fn main() { let x = 4u32; let y : &Foo<u32> = &x; <del> let fl = unsafe { fool(y as *const Foo<u32>) }; assert_eq!(fl, (43+4)*(43+4)); </del> <ins> let fl = unsafe { round_trip_and_call(y as *const Foo<u32>) }; assert_eq!(fl, (43+4)); </ins> let s = FooS([0,1,2]); let u: &FooS<[u32]> = &s;


Question:
Much of the implementation work for rust-lang/rfcs has been done, but there remain some corner cases to fix: [ ] Casts between raw pointers to different traits are accepted but should not be (e.g. ) [ ] Double-check other cases, ensure adequate tests exist
triage: P-high -- I'm giving this high priority since accepting casts that we ought not to is a backwards compatibility risk, though it is mitigated by the fact that afaik the illegal casts yield an ICE (but I haven't done exhaustive testing)
The newly-illegal casts shouldn't be ICE-s (I mean, on nightly). Casts on stable are just randomly ICE-ey.

assert_eq!(u as *const u8, p as *const u8); assert_eq!(u as *const u16, p as *const u16); <del> // ptr-ptr-cast (both vk=Length) </del> <ins> // ptr-ptr-cast (Length vtables) </ins> let mut l : [u8; 2] = [0,1]; let w: *mut [u16; 2] = &mut l as *mut [u8; 2] as *mut _; let w: *mut [u16] = unsafe {&mut *w};


Question:
Much of the implementation work for rust-lang/rfcs has been done, but there remain some corner cases to fix: [ ] Casts between raw pointers to different traits are accepted but should not be (e.g. ) [ ] Double-check other cases, ensure adequate tests exist
triage: P-high -- I'm giving this high priority since accepting casts that we ought not to is a backwards compatibility risk, though it is mitigated by the fact that afaik the illegal casts yield an ICE (but I haven't done exhaustive testing)
The newly-illegal casts shouldn't be ICE-s (I mean, on nightly). Casts on stable are just randomly ICE-ey.

let l_via_str = unsafe{&*(s as *const [u8])}; assert_eq!(&l, l_via_str); <ins> // ptr-ptr-cast (Length vtables, check length is preserved) let l: [[u8; 3]; 2] = [[3, 2, 6], [4, 5, 1]]; let p: *const [[u8; 3]] = &l; let p: &[[u8; 2]] = unsafe {&*(p as *const [[u8; 2]])}; assert_eq!(p, [[3, 2], [6, 4]]); </ins> // enum-cast assert_eq!(Simple::A as u8, 0); assert_eq!(Simple::B as u8, 1);


Question:
Right now, a fn implementing an iface method must match the purity of the iface method exactly. This is too strict. We should allow a pure fn to implement an impure fn, and both pure/impure to implement an unsafe fn. UPDATE: Updated title to reflect the real problem here. There is a FIXME in the code in the relevant area. If one declares a trait like: then in the impl, the method should take one type parameter with an bound. We don't really check this correctly though. As far as I can tell, we just check that has one type parameter with one bound, but not precisely what kind of bound it is.
Similarly, in , we require that the bounds on the method parameters be precisely equivalent, which is stronger than necessary. It is sufficient (I believe) that the bounds on the trait be stronger than the bounds on the implementation.
Is this still an issue? It seems to be fixed now.
Still an issue with respect to type parameter bounds.
I don't believe this is backwards incompatible, renominating.
accepted for feature-complete milestone
The following appears to work, but I assume that this is what was talking about:
triage bump. nothing to add.
Accepted for P-backcompat-lang
Added UPDATE to main bug description above.
I had a look at this issue and tried to create a test case. does test case covers the issue you mentioned? This test case fails because it seems like the parameter types are checked in
what error does it fail with? In the you need to use a different type bound for in order to test this issue. To be more precise, the bounds of the implementation should be implied by the bounds of the trait. For example, this should fail:
thanks for the hint, I guess your updated example should indeed test this issue. I'll start working on a patch.

let impl_m = &cm.mty; <del> if impl_m.fty.meta.purity != trait_m.fty.meta.purity { tcx.sess.span_err( cm.span, fmt!("method `%s`'s purity does  not match the trait method's  purity", tcx.sess.str_of(impl_m.ident))); } // is this check right? </del> <ins> // FIXME(#2687)---this check is too strict.  For example, a trait // method with self type `&self` or `&mut self` should be // implementable by an `&const self` method (the impl assumes less // than the trait provides). </ins> if impl_m.self_ty != trait_m.self_ty { tcx.sess.span_err( cm.span,


Question:
Right now, a fn implementing an iface method must match the purity of the iface method exactly. This is too strict. We should allow a pure fn to implement an impure fn, and both pure/impure to implement an unsafe fn. UPDATE: Updated title to reflect the real problem here. There is a FIXME in the code in the relevant area. If one declares a trait like: then in the impl, the method should take one type parameter with an bound. We don't really check this correctly though. As far as I can tell, we just check that has one type parameter with one bound, but not precisely what kind of bound it is.
Similarly, in , we require that the bounds on the method parameters be precisely equivalent, which is stronger than necessary. It is sufficient (I believe) that the bounds on the trait be stronger than the bounds on the implementation.
Is this still an issue? It seems to be fixed now.
Still an issue with respect to type parameter bounds.
I don't believe this is backwards incompatible, renominating.
accepted for feature-complete milestone
The following appears to work, but I assume that this is what was talking about:
triage bump. nothing to add.
Accepted for P-backcompat-lang
Added UPDATE to main bug description above.
I had a look at this issue and tried to create a test case. does test case covers the issue you mentioned? This test case fails because it seems like the parameter types are checked in
what error does it fail with? In the you need to use a different type bound for in order to test this issue. To be more precise, the bounds of the implementation should be implied by the bounds of the trait. For example, this should fail:
thanks for the hint, I guess your updated example should indeed test this issue. I'll start working on a patch.

return; } <ins> // FIXME(#2687)---we should be checking that the bounds of the // trait imply the bounds of the subtype, but it appears // we are...not checking this. </ins> for trait_m.tps.eachi() |i, trait_param_bounds| { // For each of the corresponding impl ty param's bounds... let impl_param_bounds = impl_m.tps[i];


Question:
Right now, a fn implementing an iface method must match the purity of the iface method exactly. This is too strict. We should allow a pure fn to implement an impure fn, and both pure/impure to implement an unsafe fn. UPDATE: Updated title to reflect the real problem here. There is a FIXME in the code in the relevant area. If one declares a trait like: then in the impl, the method should take one type parameter with an bound. We don't really check this correctly though. As far as I can tell, we just check that has one type parameter with one bound, but not precisely what kind of bound it is.
Similarly, in , we require that the bounds on the method parameters be precisely equivalent, which is stronger than necessary. It is sufficient (I believe) that the bounds on the trait be stronger than the bounds on the implementation.
Is this still an issue? It seems to be fixed now.
Still an issue with respect to type parameter bounds.
I don't believe this is backwards incompatible, renominating.
accepted for feature-complete milestone
The following appears to work, but I assume that this is what was talking about:
triage bump. nothing to add.
Accepted for P-backcompat-lang
Added UPDATE to main bug description above.
I had a look at this issue and tried to create a test case. does test case covers the issue you mentioned? This test case fails because it seems like the parameter types are checked in
what error does it fail with? In the you need to use a different type bound for in order to test this issue. To be more precise, the bounds of the implementation should be implied by the bounds of the trait. For example, this should fail:
thanks for the hint, I guess your updated example should indeed test this issue. I'll start working on a patch.

debug!("trait_fty (pre-subst): %s", ty_to_str(tcx, trait_fty)); ty::subst(tcx, &substs, trait_fty) }; <del> debug!("trait_fty: %s", ty_to_str(tcx, trait_fty)); require_same_types( tcx, None, false, cm.span, impl_fty, trait_fty, || fmt!("method `%s` has an incompatible type", tcx.sess.str_of(trait_m.ident))); </del> <ins> let infcx = infer::new_infer_ctxt(tcx); match infer::mk_subty(infcx, false, cm.span, impl_fty, trait_fty) { result::Ok(()) => {} result::Err(ref terr) => { tcx.sess.span_err( cm.span, fmt!("method `%s` has an incompatible type: %s", tcx.sess.str_of(trait_m.ident), ty::type_err_to_str(tcx, terr))); ty::note_and_explain_type_err(tcx, terr); } } </ins> return; // Replaces bound references to the self region with `with_r`.


Question:
Right now, a fn implementing an iface method must match the purity of the iface method exactly. This is too strict. We should allow a pure fn to implement an impure fn, and both pure/impure to implement an unsafe fn. UPDATE: Updated title to reflect the real problem here. There is a FIXME in the code in the relevant area. If one declares a trait like: then in the impl, the method should take one type parameter with an bound. We don't really check this correctly though. As far as I can tell, we just check that has one type parameter with one bound, but not precisely what kind of bound it is.
Similarly, in , we require that the bounds on the method parameters be precisely equivalent, which is stronger than necessary. It is sufficient (I believe) that the bounds on the trait be stronger than the bounds on the implementation.
Is this still an issue? It seems to be fixed now.
Still an issue with respect to type parameter bounds.
I don't believe this is backwards incompatible, renominating.
accepted for feature-complete milestone
The following appears to work, but I assume that this is what was talking about:
triage bump. nothing to add.
Accepted for P-backcompat-lang
Added UPDATE to main bug description above.
I had a look at this issue and tried to create a test case. does test case covers the issue you mentioned? This test case fails because it seems like the parameter types are checked in
what error does it fail with? In the you need to use a different type bound for in order to test this issue. To be more precise, the bounds of the implementation should be implied by the bounds of the trait. For example, this should fail:
thanks for the hint, I guess your updated example should indeed test this issue. I'll start working on a patch.

<ins> trait Mumbo { pure fn jumbo(&self, x: @uint) -> uint; fn jambo(&self, x: @const uint) -> uint; fn jbmbo(&self) -> @uint; } impl uint: Mumbo { // Cannot have a larger effect than the trait: fn jumbo(&self, x: @uint) { *self + *x; } //~^ ERROR expected pure fn but found impure fn // Cannot accept a narrower range of parameters: fn jambo(&self, x: @uint) { *self + *x; } //~^ ERROR values differ in mutability // Cannot return a wider range of values: fn jbmbo(&self) -> @const uint { @const 0 } //~^ ERROR values differ in mutability } fn main() {} </ins>


Question:
Right now, a fn implementing an iface method must match the purity of the iface method exactly. This is too strict. We should allow a pure fn to implement an impure fn, and both pure/impure to implement an unsafe fn. UPDATE: Updated title to reflect the real problem here. There is a FIXME in the code in the relevant area. If one declares a trait like: then in the impl, the method should take one type parameter with an bound. We don't really check this correctly though. As far as I can tell, we just check that has one type parameter with one bound, but not precisely what kind of bound it is.
Similarly, in , we require that the bounds on the method parameters be precisely equivalent, which is stronger than necessary. It is sufficient (I believe) that the bounds on the trait be stronger than the bounds on the implementation.
Is this still an issue? It seems to be fixed now.
Still an issue with respect to type parameter bounds.
I don't believe this is backwards incompatible, renominating.
accepted for feature-complete milestone
The following appears to work, but I assume that this is what was talking about:
triage bump. nothing to add.
Accepted for P-backcompat-lang
Added UPDATE to main bug description above.
I had a look at this issue and tried to create a test case. does test case covers the issue you mentioned? This test case fails because it seems like the parameter types are checked in
what error does it fail with? In the you need to use a different type bound for in order to test this issue. To be more precise, the bounds of the implementation should be implied by the bounds of the trait. For example, this should fail:
thanks for the hint, I guess your updated example should indeed test this issue. I'll start working on a patch.

<ins> trait Mumbo { fn jumbo(&self, x: @uint) -> uint; } impl uint: Mumbo { // Note: this method def is ok, it is more accepting and // less effecting than the trait method: pure fn jumbo(&self, x: @const uint) -> uint { *self + *x } } fn main() { let a = 3u; let b = a.jumbo(@mut 6); let x = @a as @Mumbo; let y = x.jumbo(@mut 6); //~ ERROR values differ in mutability let z = x.jumbo(@6); } </ins>


Question: Some : The Lifetimes chapter currently has: which does say "declares our lifetimes", so maybe further explanation isn't appropriate here, but it looks like the Functions chapter is sticking to the bare minimum. I'm not sure where this would fit, but I think the could use another sentence or two of explanation-- "This is where you declare lifetime and generic type parameters that this function is going to use" and link to the appropriate chapters for that perhaps?

fn bar<'a>(...) ``` <del> This part declares our lifetimes. This says that `bar` has one lifetime, `'a`. If we had two reference parameters, it would look like this: </del> <ins> We previously talked a little about [function syntax][functions], but we didn’t discuss the `<>`s after a function’s name. A function can have ‘generic parameters’ between the `<>`s, of which lifetimes are one kind. We’ll discuss other kinds of generics [later in the book][generics], but for now, let’s just focus on the lifteimes aspect. [functions]: functions.html [generics]: generics.html We use `<>` to declare our lifetimes. This says that `bar` has one lifetime, `'a`. If we had two reference parameters, it would look like this: </ins> ```rust,ignore fn bar<'a, 'b>(...)