diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 25e7439ece791..976849696e33a 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -125,8 +125,9 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> { // - var_infos: [E0, U1, E1, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 6 // - var_infos: [E0, U1, E1, U1, E1, E2, U2], curr_compressed_uv: 2, next_orig_uv: - // - // This algorithm runs in `O(n²)` where `n` is the number of different universe - // indices in the input. This should be fine as `n` is expected to be small. + // This algorithm runs in `O(nm)` where `n` is the number of different universe + // indices in the input and `m` is the number of canonical variables. + // This should be fine as both `n` and `m` are expected to be small. let mut curr_compressed_uv = ty::UniverseIndex::ROOT; let mut existential_in_new_uv = false; let mut next_orig_uv = Some(ty::UniverseIndex::ROOT); @@ -245,18 +246,14 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { ty::ReError(_) => return r, }; - let existing_bound_var = match self.canonicalize_mode { - CanonicalizeMode::Input => None, - CanonicalizeMode::Response { .. } => { - self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from) - } - }; - let var = existing_bound_var.unwrap_or_else(|| { - let var = ty::BoundVar::from(self.variables.len()); - self.variables.push(r.into()); - self.primitive_var_infos.push(CanonicalVarInfo { kind }); - var - }); + let var = ty::BoundVar::from( + self.variables.iter().position(|&v| v == r.into()).unwrap_or_else(|| { + let var = self.variables.len(); + self.variables.push(r.into()); + self.primitive_var_infos.push(CanonicalVarInfo { kind }); + var + }), + ); let br = ty::BoundRegion { var, kind: BrAnon(None) }; self.interner().mk_re_late_bound(self.binder_index, br) } diff --git a/tests/ui/regions/issue-2718.rs b/tests/ui/regions/issue-2718.rs deleted file mode 100644 index 6449337eea4e7..0000000000000 --- a/tests/ui/regions/issue-2718.rs +++ /dev/null @@ -1,327 +0,0 @@ -// run-pass -#![allow(dead_code)] -#![allow(unused_unsafe)] -#![allow(unused_imports)] -#![allow(non_camel_case_types)] - -pub type Task = isize; - -// tjc: I don't know why -pub mod pipes { - use self::state::{empty, full, blocked, terminated}; - use super::Task; - use std::mem::{forget, transmute}; - use std::mem::{replace, swap}; - use std::mem; - use std::thread; - use std::marker::Send; - - pub struct Stuff { - state: state, - blocked_task: Option, - payload: Option - } - - #[derive(PartialEq, Debug)] - #[repr(isize)] - pub enum state { - empty, - full, - blocked, - terminated - } - - pub struct packet { - state: state, - blocked_task: Option, - payload: Option - } - - unsafe impl Send for packet {} - - pub fn packet() -> *const packet { - unsafe { - let p: *const packet = mem::transmute(Box::new(Stuff{ - state: empty, - blocked_task: None::, - payload: None:: - })); - p - } - } - - mod rusti { - pub fn atomic_xchg(_dst: &mut isize, _src: isize) -> isize { panic!(); } - pub fn atomic_xchg_acq(_dst: &mut isize, _src: isize) -> isize { panic!(); } - pub fn atomic_xchg_rel(_dst: &mut isize, _src: isize) -> isize { panic!(); } - } - - // We should consider moving this to ::std::unsafe, although I - // suspect graydon would want us to use void pointers instead. - pub unsafe fn uniquify(x: *const T) -> Box { - mem::transmute(x) - } - - pub fn swap_state_acq(dst: &mut state, src: state) -> state { - unsafe { - transmute(rusti::atomic_xchg_acq(transmute(dst), src as isize)) - } - } - - pub fn swap_state_rel(dst: &mut state, src: state) -> state { - unsafe { - transmute(rusti::atomic_xchg_rel(transmute(dst), src as isize)) - } - } - - pub fn send(mut p: send_packet, payload: T) { - let p = p.unwrap(); - let mut p = unsafe { uniquify(p) }; - assert!((*p).payload.is_none()); - (*p).payload = Some(payload); - let old_state = swap_state_rel(&mut (*p).state, full); - match old_state { - empty => { - // Yay, fastpath. - - // The receiver will eventually clean this up. - unsafe { forget(p); } - } - full => { panic!("duplicate send") } - blocked => { - - // The receiver will eventually clean this up. - unsafe { forget(p); } - } - terminated => { - // The receiver will never receive this. Rely on drop_glue - // to clean everything up. - } - } - } - - pub fn recv(mut p: recv_packet) -> Option { - let p = p.unwrap(); - let mut p = unsafe { uniquify(p) }; - loop { - let old_state = swap_state_acq(&mut (*p).state, - blocked); - match old_state { - empty | blocked => { thread::yield_now(); } - full => { - let payload = replace(&mut p.payload, None); - return Some(payload.unwrap()) - } - terminated => { - assert_eq!(old_state, terminated); - return None; - } - } - } - } - - pub fn sender_terminate(p: *const packet) { - let mut p = unsafe { uniquify(p) }; - match swap_state_rel(&mut (*p).state, terminated) { - empty | blocked => { - // The receiver will eventually clean up. - unsafe { forget(p) } - } - full => { - // This is impossible - panic!("you dun goofed") - } - terminated => { - // I have to clean up, use drop_glue - } - } - } - - pub fn receiver_terminate(p: *const packet) { - let mut p = unsafe { uniquify(p) }; - match swap_state_rel(&mut (*p).state, terminated) { - empty => { - // the sender will clean up - unsafe { forget(p) } - } - blocked => { - // this shouldn't happen. - panic!("terminating a blocked packet") - } - terminated | full => { - // I have to clean up, use drop_glue - } - } - } - - pub struct send_packet { - p: Option<*const packet>, - } - - impl Drop for send_packet { - fn drop(&mut self) { - unsafe { - if self.p != None { - let self_p: &mut Option<*const packet> = - mem::transmute(&mut self.p); - let p = replace(self_p, None); - sender_terminate(p.unwrap()) - } - } - } - } - - impl send_packet { - pub fn unwrap(&mut self) -> *const packet { - replace(&mut self.p, None).unwrap() - } - } - - pub fn send_packet(p: *const packet) -> send_packet { - send_packet { - p: Some(p) - } - } - - pub struct recv_packet { - p: Option<*const packet>, - } - - impl Drop for recv_packet { - fn drop(&mut self) { - unsafe { - if self.p != None { - let self_p: &mut Option<*const packet> = - mem::transmute(&mut self.p); - let p = replace(self_p, None); - receiver_terminate(p.unwrap()) - } - } - } - } - - impl recv_packet { - pub fn unwrap(&mut self) -> *const packet { - replace(&mut self.p, None).unwrap() - } - } - - pub fn recv_packet(p: *const packet) -> recv_packet { - recv_packet { - p: Some(p) - } - } - - pub fn entangle() -> (send_packet, recv_packet) { - let p = packet(); - (send_packet(p), recv_packet(p)) - } -} - -pub mod pingpong { - use std::mem; - - pub struct ping(::pipes::send_packet); - - unsafe impl Send for ping {} - - pub struct pong(::pipes::send_packet); - - unsafe impl Send for pong {} - - pub fn liberate_ping(p: ping) -> ::pipes::send_packet { - unsafe { - let _addr : *const ::pipes::send_packet = match &p { - &ping(ref x) => { mem::transmute(x) } - }; - panic!() - } - } - - pub fn liberate_pong(p: pong) -> ::pipes::send_packet { - unsafe { - let _addr : *const ::pipes::send_packet = match &p { - &pong(ref x) => { mem::transmute(x) } - }; - panic!() - } - } - - pub fn init() -> (client::ping, server::ping) { - ::pipes::entangle() - } - - pub mod client { - use pingpong; - - pub type ping = ::pipes::send_packet; - pub type pong = ::pipes::recv_packet; - - pub fn do_ping(c: ping) -> pong { - let (sp, rp) = ::pipes::entangle(); - - ::pipes::send(c, pingpong::ping(sp)); - rp - } - - pub fn do_pong(c: pong) -> (ping, ()) { - let packet = ::pipes::recv(c); - if packet.is_none() { - panic!("sender closed the connection") - } - (pingpong::liberate_pong(packet.unwrap()), ()) - } - } - - pub mod server { - use pingpong; - - pub type ping = ::pipes::recv_packet; - pub type pong = ::pipes::send_packet; - - pub fn do_ping(c: ping) -> (pong, ()) { - let packet = ::pipes::recv(c); - if packet.is_none() { - panic!("sender closed the connection") - } - (pingpong::liberate_ping(packet.unwrap()), ()) - } - - pub fn do_pong(c: pong) -> ping { - let (sp, rp) = ::pipes::entangle(); - ::pipes::send(c, pingpong::pong(sp)); - rp - } - } -} - -fn client(chan: pingpong::client::ping) { - let chan = pingpong::client::do_ping(chan); - println!("Sent ping"); - let (_chan, _data) = pingpong::client::do_pong(chan); - println!("Received pong"); -} - -fn server(chan: pingpong::server::ping) { - let (chan, _data) = pingpong::server::do_ping(chan); - println!("Received ping"); - let _chan = pingpong::server::do_pong(chan); - println!("Sent pong"); -} - -pub fn main() { - /* -// Commented out because of option::get error - - let (client_, server_) = pingpong::init(); - - task::spawn {|client_| - let client__ = client_.take(); - client(client__); - }; - task::spawn {|server_| - let server__ = server_.take(); - server(server_ˊ); - }; - */ -} diff --git a/tests/ui/traits/new-solver/iter-filter-projection.rs b/tests/ui/traits/new-solver/iter-filter-projection.rs new file mode 100644 index 0000000000000..8fb62323aa5a7 --- /dev/null +++ b/tests/ui/traits/new-solver/iter-filter-projection.rs @@ -0,0 +1,12 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +use std::{iter, slice}; + +struct Attr; + +fn test<'a, T: Iterator>() {} + +fn main() { + test::, fn(&&Attr) -> bool>>(); +}