Skip to content
This repository

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

Closed
BigEndian opened this Issue October 05, 2012 · 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
Collaborator

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

Tim Chevalier
Collaborator

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
Collaborator

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

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

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

Closes #3668
c5b82a6
Tim Chevalier catamorphism closed this in c5b82a6 October 15, 2012
Jay Anderson jayanderson referenced this issue from a commit November 10, 2013
Commit has since been removed from the repository and is no longer available.
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.