Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

crash: compile-time typeck/check.rs failure #3668

Closed
BigEndian opened this Issue · 4 comments

3 participants

Eric Tim Chevalier Niko Matsakis
Eric

Result of attempted compilation:

rust: task failed at 'Assertion fcx.inh.locals.contains_key(nid) failed', /Users/superjapanfreak/build/rust/src/rustc/middle/typeck/check.rs:2388
error: internal compiler error: unexpected failure
note: the compiler hit an unexpected failure path. this is a bug
note: try running with RUST_LOG=rustc=0,::rt::backtrace to get further details and report the results to github.com/mozilla/rust/issues
rust: task failed at 'explicit failure', /Users/superjapanfreak/build/rust/src/rustc/driver/rustc.rs:275
rust: domain main @0x7fb97b800010 root task failed
rust: task failed at 'killed', /Users/superjapanfreak/build/rust/src/libcore/task.rs:705
struct Employee { name: ~str, mut employer: Option<@Business> }                                                                                                                    
struct Business { name: ~str, mut boss: Option<@mut Employee>, mut employees: ~[Option<@mut Employee>] }                                                                           

trait EmployeeTrait {                                                                                                                                                              
   pure fn isEmployed() -> bool;                                                                                                                                                   
   fn setEmployer(employer: @Business);                                                                                                                                            
}                                                                                                                                                                                  

impl Employee: EmployeeTrait {                                                                                                                                                        pure fn isEmployed() -> bool {                                                                                                                                                        self.employer.is_some()                                                                                                                                                      
   }                                                                                                                                                                               
   fn setEmployer(employer: @Business) {                                                                                                                                           
      self.employer = Some(employer);                                                                                                                                              
   }                                                                                                                                                                               
}                                                                                                                                                                                  

trait BusinessTrait {                                                                                                                                                              
   fn fireBoss() -> bool;                                                                                                                                                          
   fn hireBoss(e: @mut Employee);                                                                                                                                                  
   fn getBossOption() -> Option<@Employee>;                                                                                                                                        
}                                                                                                                                                                                  

impl Business: BusinessTrait {                                                                                                                                                     
   fn fireBoss() -> bool {                                                                                                                                                         
      if self.boss.is_none() {                                                                                                                                                     
         return false;                                                                                                                                                             
      }                                                                                                                                                                            
      let oldBoss = self.boss.get();                                                                                                                                               
      oldBoss.employer = None;                                                                                                                                                     
      self.boss = None;                                                                                                                                                            
      true                                                                                                                                                                         
   }                                                                                                                                                                               
   fn hireBoss(newBoss: @mut Employee) {                                                                                                                                           
      if self.boss.is_some() {                                                                                                                                                     
         self.fireBoss();                                                                                                                                                          
      }                                                                                                                                                                            
      newBoss.setEmployer(@copy self);                                                                                                                                             
      self.boss = Some(newBoss);                                                                                                                                                   
   }                                                                                                                                                                               
   fn getBossOption() -> Option<@Employee> {                                                                                                                                       
      let opt: Option<@Employee> = None;                                                                                                                                           
      if self.boss.is_some() {                                                                                                                                                     
         const bossCopy: @Employee = self.boss.get();                                                                                                                              
         opt = Some(bossCopy);                                                                                                                                                     
      }                                                                                                                                                                            
      opt                                                                                                                                                                          
   }                                                                                                                                                                               
}                                                                                                                                                                                  

fn main() {                                                                                                                                                                        
   let bob = @mut Employee { name: ~"Bob Newhart", employer: None };
   let restaurant = Business { name: ~"In-N-Out", boss: Some(bob), employees: ~[] };                                                                                               

   io::println(#fmt("Bob is %s", if bob.isEmployed() { ~"employed" } else { ~"not employed" }));                                                                                   
} 
Eric

Updated test case:

struct P { child: Option<@mut P> }                                                                                                                                                                                                                                                                                                                                    
trait PTrait {                                                                                                                                                                     
   fn getChildOption() -> Option<@P>;                                                                                                                                              
}                                                                                                                                                                                  

impl P: PTrait {                                                                                                                                                                   
   fn getChildOption() -> Option<@P> {                                                                                                                                             
      let opt: Option<@P> = None;                                                                                                                                                        if self.child.is_some() {                                                                                                                                                             const childVal: @P = self.child.get();                                                                                                                                    
         opt = Some(childVal);                                                                                                                                                     
      }                                                                                                                                                                            
      opt                                                                                                                                                                          
   }                                                                                                                                                                               
}
Tim Chevalier catamorphism was assigned
Tim Chevalier

I'll take a look while waiting for snapshots to finish...

Tim Chevalier

An even smaller program that exhibits the same bug:

fn f(x:int) {
    const child: int = x + 1;
}

fn main() {}

The problem is that this isn't an acceptable RHS for a constant, as in your example as well. But, constant checking happens after typechecking. The typechecker, though, assumes constants don't refer to things like self or args. This is a bad assumption to make. To fix this, either we have to pass a function context to checking nested consts, or check constants before typechecking (constant checking uses some tables generated by the typechecker, though). It's a pain either way. But should be fixed.

Niko Matsakis
Owner

This seems like a resolve bug. Resolve should understand the scoping for constant declarations.

Tim Chevalier catamorphism referenced this issue from a commit
Tim Chevalier catamorphism Add test cases for #3668
Previous commits fix the issue.

Closes #3668
c5b82a6
Tim Chevalier catamorphism closed this issue from a commit
Tim Chevalier catamorphism Add test cases for #3668
Previous commits fix the issue.

Closes #3668
c5b82a6
Jay Anderson jayanderson referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
Tim Chevalier catamorphism was unassigned by BigEndian
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.